What is the difference between and.stub vs and.callFake in Jasmine
Asked Answered
H

2

11

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
    });
Hollishollister answered 18/3, 2018 at 6:18 Comment(1)
One of the things to note is your example passes a function to the stub() method; however, there is no method signature for stub that accepts a parameter. That is the first hint.Bentz
B
20

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')

Bentz answered 30/5, 2018 at 23:35 Comment(0)
N
0

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; })

Nerynesbit answered 17/4, 2023 at 20:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.