Using spyOn with different Options

  1. Using spyon with callThrough would make the call to actual service
  2. spyOn with returnValue returns the value specified without making call to real function
  3. spyOn withArgs does the same but takes arguments incase there is somelogic needs to change when using along callthrough
  4. spyOn callFake would run anonymous function withits own logic rather than calling original function to act on logic
spyOn(empService, 'authenticateEmp').withArgs('Admin').and.callThrough();

spyOn(empService, 'authenticateEmp').and.returnValue(true);

spyOn(empService, 'authenticateEmp').withArgs('Admin').and.returnValue(true);

spyOn(empService, 'authenticateEmp').and.callFake(function(name, args){
   return true;
});

What is difference between returnValue and callFake?
If we just want a return value when a service method is called then we can use any of and.callFake or and.returnValue. Lets take below example

component file:

@Component(...)
export class DependencyComponent {
  constructor(private service: RandomService){....}
  .....
  sampleMethod() {
   return this.service.randomMethod();
  }
  .....
}

unit test case for above component:

it('test callFake vs returnValue', () => {
  let randomService= new RandomService();
  let component = new DependencyComponent(randomService);
  spyOn(randomService, 'randomMethod').and.callFake(() => 4)
  expect(component.sampleMethod()).toBe(4)
  spyOn(randomService, 'randomMethod').and.returnValue(10);
  expect(component.sampleMethod()).toBe(10)
})

in above case both the ways are correct.

Suppose we are passing a parameter to service method to perform its logic then in that case we have to use and.callFake((param) => {…}). Here param parameter will be the argument passed to the spied method.

component file:

@Component(...)
export class DependencyComponent {
  constructor(private service: RandomService){....}
  .....
  sampleMethod(val) {
  return this.service.randomMethod(val);
  }
  .....
}

unit test case for above component:

it('test callFake vs returnValue', () => {
  let randomService= new RandomService();
  let component = new DependencyComponent(randomService);
  spyOn(randomService, 'randomMethod').and.callFake((param) => param+4)
  expect(component.sampleMethod(4)).toBe(8);
  expect(component.sampleMethod(12)).toBe(16)
})

when component.sampleMethod(4) is executed it will call this.service.randomMethod(4). As randomMethod() is being spied using and.callFake therefore 4 will be passed as argument of call back function of and.callFake.

One obvious question is can i use returnValue instead of callFake? You can still use but you need to define multiple returnValue methods based on total arguments needs to be tested.

Comments are closed.