Home > Software design >  Why sometimes second test executes after first one with Angular Jasmine Unit Testing?
Why sometimes second test executes after first one with Angular Jasmine Unit Testing?

Time:10-16

I am learning how to Angular Test and something strange happens to me. Thing is, WITH THE SAME EXACT CODE, when I do ng test sometimes the substract IT block is executed before the add IT block, when this one is supposed to be executed the first (and sometimes it actually does):

This is the spec code:

import { CalculatorService } from './calculator.service';
describe ('calculatorService',()=>{

    let calculator:CalculatorService;
    let loggerSpy:any;

    beforeEach(()=>{

        console.log ("calling the beforeEach");

        loggerSpy=jasmine.createSpyObj('LoggerServiceSpy', ['log']);

        calculator= new CalculatorService(loggerSpy);

    });


    it('should add two numbers', ()=>{


        let result=calculator.add(2,2);

        console.log ("add test");

        expect(result).toBe(4);
        expect(loggerSpy.log).toHaveBeenCalledTimes(1);
    });

    it('should substract two numbers', ()=>{




        let result=calculator.subtract(2,2);

        console.log ("substract test");

        expect(result).toBe(0, "unexpected substracion result");
        expect(loggerSpy.log).toHaveBeenCalledTimes(1);

        
    });

});

And this what I obtain sometimes:

enter image description here

Other times I just kill terminal (integrated terminal in Visual Studio Code, it this helps you), execute ng test again, and normal flow is done... What am I doing wrong?

enter image description here

EDIT: I add the calculator and logger services code in case it helps (also I don´t know why this.logger.log test is not outputed when I do the ng test but I guess that is another question

calculator-service.ts

import {Injectable} from '@angular/core';
import {LoggerService} from './logger.service';


@Injectable({
  providedIn: 'root'
})
export class CalculatorService {


  constructor(private logger: LoggerService) {

  }

  add(n1: number, n2:number) {
    this.logger.log("Addition operation called");

    return n1   n2;
  }

  subtract(n1: number, n2:number) {
    this.logger.log("Subtraction operation called");
    return n1 - n2;
  }


}

logger-service.ts


import {Injectable} from '@angular/core';


@Injectable({
  providedIn: 'root'
})
export class LoggerService {

  log(message:string) {
    console.log(message);
  }

}

CodePudding user response:

The reason for this is that Jasmine executes tests in a random order by default. This can be changed by setting random: false in your karma.conf file under the jasmine property as shown here in the README.

This default behavior of running your unit tests randomly is actually a good thing, however. A general principle of writing good unit tests is to write them in such a way as they are fully self-contained -- meaning, each test has everything it needs to execute by itself. If your tests have to run in a specific order in order to pass, it generally means the tests depend on each other, and this is considered bad practice.

If you have to run your tests in a specific order for some reason though, you can certainly do so.

  • Related