I have a scenario whereby I want to call done()
on a beforeEach
after a callback has been invoked.
I tried to do this as follows :
spyOn(scope, 'onAdmin').and.callThrough().and.callFake(function(){done()})
But I'm not sure I get the right behaviour. Essentially what I want to achieve is to be able to call done()
after each callback is done doing what it does.
UPDATE: workaround solution
scope.onAdminBackup = scope.onAdmin;
spyOn(scope, 'onAdmin').and.callFake(function(admin) {
scope.onAdminBackup();
done() ;
})
callThrough spy. This spy will track calls to the function it is spying on, but it will also pass through to the function and allow it to run. This means that when we use this spy, the function being spied on will still do what it is written to do, but we can track the calls to it.
callFake() Test doubles like mocks, spies, and stubs are integral part of unit testing. In Jasmine, there are few such functions which can stub any function and track calls to it and all its arguments.
Jasmine spies are used to track or stub functions or methods. Spies are a way to check if a function was called or to provide a custom return value. We can use spies to test components that depend on service and avoid actually calling the service's methods to get a value.
I found a work around way to do this. Jasmine has a method called addSpyStategy where you can add a custom strategy like callThrough or callFake. It would look something like this:
jasmine.addSpyStrategy('callThroughAndThen', (spy, fn) => {
return function() {
spy.and.callThrough();
setTimeout(() => fn(...arguments), 0);
}
});
the timeout makes sure the real function finishes before executing the custom function. Then for your spy, you can do this:
const spy = spyOn(scope, 'onAdmin')
spy.and.callThroughAndThen(spy, () => {
// your custom callback
done();
});
note: make sure to put custom strategy in a beforeEach block
I have never chained these kinds of functions together cuz in my mind they seem to do the opposite. You are saying when I call this method -onAdmin - in the scope call it as normal. Which is what the callThrough method jasmine provides for us does.
But then you are chaining along a callFake method as well so then you say but dont actually call it call this fake function instead - very conflicting.
If you want to call spy on the method onAdmin and instead of it being fired you want it to do something else - something mocked - then use the .and.callFake(fn). Also take into account like @stefan above said - dont invoke the function - callFake is simply wanting a function as a parameter it will take care of calling it itself.
This might be more along the lines of what you are looking for, if not show us some more code.
spyOn(scope, 'onAdmin')and.callFake(done)
you are calling done right-away when you write done() try passing in done as a value:
spyOn(scope, 'onAdmin').and.callThrough().and.callFake(done)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With