I have an angular controller with a method that calls $location.search()
twice.
First time is just $location.search()
to return the value.
Second time is $location.search("foo", null)
to clear it.
I have the following spy in my unit test:spyOn($location, "search").and.returnValue({ foo: "bar" });
It appears the spy returns {foo:"bar"}
even when my implementation does $location.search("foo", null)
.
I need a way to have two different spies for the same method depending on the arguments.
I need this expect:expect($location.search().foo).toEqual(null);
to pass at the end of the unit test.
You can go about it different ways. If you have time to change the spy implementation during your testcase, you can do this:
var searchSpy = spyOn($location,'search');
searchSpy.and.returnValue(null);
// do stuff
searchSpy.and.returnValue({ foo: "bar" });
// do other stuff
If the calls are triggered by a method in your code, and you cannot change the spy implementation in between, then you can create a function that takes the arguments and responds appropriately:
spyOn($location,'search').and.callFake(function(someParam){
if (someParam) {
return { foo: "bar" };
} else {
return { foo: null };
}
});
Of course you can go crazy with logic in your callFake implementation, but beware, I think in that case it might be a code smell. Anyway, happy coding!
Also it's possible to call spy properties on the mocked object directly. The code may look like:
spyOn($location,'search');
$location.search.and.returnValue(null);
// do stuff
$location.search.and.returnValue({ foo: "bar" })
// do other stuff
In case of typescript it may look like:
spyOn($location,'search');
(<jasmine.Spy>$location.search).and.returnValue(null);
// do stuff
(<jasmine.Spy>$location.search).and.returnValue({ foo: "bar" })
// do other stuff
Posting this answer because it may look a bit cleaner and doesn't require additional variables.
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