Angular unit testing with Jasmine: how to remove or modify spyOn

JavascriptAngularjsUnit TestingJasmineKarma Jasmine

Javascript Problem Overview


AngularJS v1.2.26

Jasmine v2.2.0

How can I change or remove the behavior of a spyOn? When I try to override it, I get the following error: Error: getUpdate has already been spied upon

var data1 = 'foo';
var data2 = 'bar';

describe("a spec with a spy", function(){

    beforeEach(module('app'));

    var $q;

    beforeEach(inject(function(_updateService_, _$q_){
        updateService = _updateService_;

        //spy the results of the getUpdate()
        $q = _$q_;
        var deferred = $q.defer();
        deferred.resolve( data1 );
        spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);

    }));

    describe('and here the spy should be different', function() {

        it('returns a different value', function() {

          var deferred = $q.defer();
          deferred.resolve( data2 );
          spyOn(updateService, 'getUpdate'); //ERROR HERE
          updateService.getUpdate.and.returnValue(deferred.promise);

          ...

        });
    });

...

When I remove the second spyOn the test doesn't work.

How do I do this?

Javascript Solutions


Solution 1 - Javascript

You can just overwrite it

updateService.getUpdate = jasmine.createSpy().and.returnValue(etc)

Solution 2 - Javascript

You can override the return value of the spy

    var deferred = $q.defer();
    deferred.resolve( data1 );

    var getUpdateSpy = spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);



    var newDeferred = $q.defer();
    newDeferred.resolve( data2 );

    getUpdateSpy.and.returnValue(newDeferred.promise);        
    
    
    

Solution 3 - Javascript

Since jasmine v2.5, use the global allowRespy() setting.

jasmine.getEnv().allowRespy(true);

You'll be able to call spyOn() multiple times, when you don't want and/or have access to the first spy. Beware it will return the previous spy, if any is already active.

spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);
...
spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);

Solution 4 - Javascript

More easier and simpler way:

updateService.getUpdate.and.returnValue(Observable.of({status:true}));

It will return the value.

Solution 5 - Javascript

Another option:

(yourService.method as jasmine.Spy).and.returnValue(value);

Solution 6 - Javascript

the green check-marked answer didn't work for me, but this did:

yourCoolService.createThing = jasmine.createSpy('notreal', function(){}).and.returnValue();

your jasmine test will run but when you go to fire up your app typescript will yell loudly at you if you don't put a random string and an empty function as the args to createSpy().

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionemersonthisView Question on Stackoverflow
Solution 1 - JavascriptPeter AshwellView Answer on Stackoverflow
Solution 2 - JavascriptJavier Candalaft-CONTView Answer on Stackoverflow
Solution 3 - JavascriptAndré WerlangView Answer on Stackoverflow
Solution 4 - JavascriptAniruddha DasView Answer on Stackoverflow
Solution 5 - JavascriptJustinas JakavonisView Answer on Stackoverflow
Solution 6 - Javascriptrb1econView Answer on Stackoverflow