Overwriting Mocks in Jasmine

1 minute read

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)

Leave a Comment