Overwriting Mocks in Jasmine
TIL how to overwrite mocks in tests, by saving them to a variable and modifying the function tied to the object.
During my test-a-palooza (technical term) over the past few days, I have been learning a lot of advanced jasmine techniques.
In my test file, I found that I wanted to overwrite a spy that I had previously created in a beforeEach
. Here is an example of the spy:
beforeEach(function(){
spyOn(serviceName, 'serviceMethod').and.callFake(function(){
var deferred = $q.defer();
deferred.resolve(mock_data);
return deferred.promise;
});
});
The spy above is overriding
the method call to the service that interfaces with our application backend to fetch data. It is returning a resolved promise with mock_data, which imitates a successful HTTP request…
…but now I need to test how my controller handles an unsuccessful response from the backend! If I try to create a new spy in my method, Jasmine throws an error saying spy on serviceName, serviceMethod already exists
.
The solution:
The spyOn
method returns the created spy as an object when it is invoked. If you just save that object to a variable, you can delete it as necessary and re-create it to return a rejected promise in my edge case test!
Even Better:
Instead of deleting the spy completely, it is possible to just override the method again with a new callFake
!
beforeEach(function(){
// create a variable to store the spy
var serviceSpy = spyOn(serviceName, 'serviceMethod').and.callFake(function(){
var deferred = $q.defer();
deferred.resolve(mock_data); // resolved promise
return deferred.promise;
});
it('should handle a rejected promise appropriately', function(){
// use the variable to overwrite the fake method in this test ONLY
serviceSpy.and.callFake(function(){
var deferred = $q.defer();
deferred.reject({message: 'error'}); // rejected promise
return deferred.promise;
});
//assertions here
});
});
Furthermore, if a spy already exists for a dependency but you need to call the actual implementation of that dependency again temporarily for a test, you can use spy.and.callThrough()
to overwrite the fake method with the original implementation
Spys rock, and make testing SO much easier than it ever has been. I thought I had a good grasp on spys and when to use them, but now I feel like agent M deploying 007 all OVER these controllers and services.
get it? spys???
(badjokeeel)
Comments