Angular unit testing with Jasmine: how to remove or modify spyOn
Solution 1
You can just overwrite it
updateService.getUpdate = jasmine.createSpy().and.returnValue(etc)
Solution 2
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
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
More easier and simpler way:
updateService.getUpdate.and.returnValue(Observable.of({status:true}));
It will return the value.
Solution 5
Another option:
(yourService.method as jasmine.Spy).and.returnValue(value);
Related videos on Youtube
emersonthis
I am a designer, developer, and problem solver. I make websites and stuff. I work with brazen startups, modest individuals, earnest small business, and everyone in between. I care as much about how things look as how they work. I enjoy writing and teaching what I know. The best part about my job is constantly learning new things.
Updated on July 31, 2021Comments
-
emersonthis almost 3 years
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?
-
Bohdan Lyzanets over 4 yearsPossible duplicate of Jasmine SpyOn same method more than once
-
-
emersonthis about 9 yearsIs there way to remove the spy entirely? To go back to the original function?
-
Jan almost 9 yearsThe big question is, if you don't the same functionality in every test, why have a global spy at all? If you want to set the spy for every test, then set the spy for every test.
-
theblang almost 8 years@Jan If I have fifty tests, and only one of them has a spy for a function that is different from the rest, I'd rather just change it the one time there instead of every single test.
-
FlavorScape about 7 yearswell, in my case it's on a global object (defined by native code). So I have multiple specs that need to return different values in different situations....
-
MBielski over 6 yearsThis is probably due to an updated version of Jasmine. I am using 2.7 and this works for me.
-
camleng over 5 yearsThank you. Everyone else is missing the obvious answer.
-
George C. almost 5 yearsWorks on 18/6/2019
-
Novastorm almost 5 yearsHonestly, this is the answer I've been looking for ages. I wish it was more prevalent on the internet. A million thanks :)
-
GarfieldKlon over 4 yearsThat may work if all your code is in the same describe, but otherwise not because getUpdateSpy is not defined...
-
aj go over 3 yearswould it return to its original implementation by calling jasmine.createSpy().and.callThrought()?
-
Samuel Bushi over 3 years@GarfieldKlon You can work around that by defining the variable
getUpdateSpy
in the parentdescribe
block. -
ANeves about 3 yearsIt seems that your type system is not complaining. That begs the question: why use Typescript at all?