Search code examples
angularjasminetestbed

Spy return value is not work correctly in Service test using jasmine


I'm not able to correctly mock my return value of a function inside my injected service in my Angular test.

I'm using:

jasmine v2.8.0 and jasmine-core v2.8.0

I simplified the code to make it easier to understand. Here it is...

This is my Service what I want to test:

export class NetworkService {

  testNumber = 0;

  constructor(private networkReducerService: NetworkReducerService) {
    this.testNumber = networkReducerService.getNumber();
  }
}

This is my spec.ts

describe('NetworkService', () => {

  let service: NetworkService;
  let networkReducerServiceSpy: jasmine.SpyObj<NetworkReducerService>;

  beforeEach(() => {

    const nRServiceSpy = jasmine.createSpyObj('NetworkReducerService', ['getNumber']);

    TestBed.configureTestingModule({
      providers: [NetworkService,
        {provide: NetworkReducerService, useValue: nRServiceSpy}
      ]
    });
    service = TestBed.get(NetworkService);
    networkReducerServiceSpy = TestBed.get(NetworkReducerService);
  });

  it('should have the following fields', () => {

    networkReducerServiceSpy.getNumber.and.returnValue(1);

    expect(networkReducerServiceSpy.getNumber).toHaveBeenCalled();

    expect(service.testNumber).toBe(1);
  });

});

I want to mock this getNumber method inside my NetworkReducerService

@Injectable({
  providedIn: 'root'
})
export class NetworkReducerService {
  getNumber() {
    return 1;
  }
}

I get the following error:

Error: Expected undefined to be 1.


Solution

  • You are running into an "a before b" issue. You make the call to set testNumber in the constructor of your NetworkService class. Therefore it is called when you first create the class - long before you change the value of your spy. Either set the value before you instantiate the service, or refactor your NetworkService to set the value inside a method that can be tested by invoking after creation, rather than the constructor.