Reputation: 7069
I am a newbie to Jasmine
and a bit confused between above two functions. My sole purpose is to give a fake implementation to a spy function. But, If I put debugger in callFake
the it is getting called but and.stub
's function is not getting called. Could anyone please explain what is the difference between these two functions.
spyOn(manager, 'getUsers').and.stub(function () {
//to do
});
vs
spyOn(manager, 'getUsers').and.callFake(function () {
//to do
});
Upvotes: 11
Views: 30421
Reputation: 586
Looking at the documentation located at https://jasmine.github.io/2.0/introduction.html#section-Spies, when you spyOn
something it logs of all the calls being made on the spied on object method. This means that it is calling the actual method of the object, but keeping track of what calls were made.
If you want to allow using the original object, but don't want specific methods to be called, you have the options of using and.callFake
and and.stub
. The differences are in the method signatures.
callFake
takes a function as a parameter. This allows you to fake the method call and return the value you desire.
original method signature is myMethod(param1: string): string
spyOn(service, 'myMethod').and.callFake((param1) => {
expect(param1).toBe('value');
return 'returnValue';
});
stub
has no parameters and merely intercepts the call to the method
spyOn(service, 'myMethod').and.stub();
myMethod can have parameters and can have a return type, but it doesn't matter since stub just intercepts the call and will return null
if there is a return type.
In both instances, the method calls are logged and you can then do something like expect(service.myMethod).toHaveBeenCalled()
or expect(service.myMethod).toHaveBeenCalledWith('value')
Upvotes: 20
Reputation: 907
So, let mySpy = spyOn(service, 'myMethod').and.stub()
is the exact same as let mySpy = spyOn(service, 'myMethod')
. Both of these do the same 2 things:
1 - they will wait until that function is called and can report back on it later and tell you if it was called via expect(mySpy).toHaveBeenCalled()
.
2 - they intercept the function and NEVER call it. So if you spy on a function, it doesn't actually get called. Which is extremely useful when paired with let mySpy = spyOn(service, 'myMethod').and.returnValue(someUsefulReturnValue)
.
However, as a side note, in some situations you want to spy on a function to see if it was called, write an expectation that it was called, BUT actually allow it to get called, which is when you would use let mySpy = spyOn(service, 'myMethod').and.callThrough()
Whereas, let mySpy = spyOn(service, 'myMethod').and.callFake()
does the same 2 things in the bullet points above, except with one benefit. You can call a function inside of callFake()
that will execute inside of myMethod
. I find this is not extremely useful when following programming principles, and is used less often.
I.e. let mySpy = spyOn(service, 'myMethod').and.callFake(() => { this.somethingThatNeedsToBeUpdated = somethingUseful; })
Upvotes: 0