I've got the following service:
angular.module("services")
.factory("whatever", function($window) {
return {
redirect: function() {
$window.location.replace("http://www.whatever.com");
}
};
});
How to mock $window
object in unit test to prevent reloading the page when running tests?
I tried using
spyOn($window.location, 'replace').andReturn(true);
, but it didn't work (still got "Some of your tests did a full page reload!"
error) and
$provide.value('$window', {location: {replace: jasmine.createSpy()}})
, but I was getting an error (Error: [ng:areq] Argument 'fn' is not a function, got Object
) with stack trace pointing only to angular own source, so it wasn't very helpful...
In Chrome (didn't test inother browsers), location.replace is readonly so spyOn wasn't able to replace it.
$provide.value
should work. Something must be wrong somewhere in your code.
Here is a working unit test
describe('whatever', function() {
var $window, whatever;
beforeEach(module('services'));
beforeEach(function() {
$window = {location: { replace: jasmine.createSpy()} };
module(function($provide) {
$provide.value('$window', $window);
});
inject(function($injector) {
whatever = $injector.get('whatever');
});
});
it('replace redirects to http://www.whatever.com', function() {
whatever.redirect();
expect($window.location.replace).toHaveBeenCalledWith('http://www.whatever.com');
});
});
I'm going with an easier but perhaps less elegant solution. I'm writing a wrapper for $window.location, which I can then mock. Relating that to your code, I'd be mocking the whatever.redirect function, rather than mocking $window (I'm assuming here that your real function is more complex).
So I'd end up with:
angular.module("services")
.factory("whatever", function($window) {
return {
do_stuff_that_redirects: function() {
lots of code;
this.redirect("http://www.whatever.com");
maybe_more_code_maybe_not;
},
redirect: function(url) {
$window.location.replace(url);
}
};
});
I can then directly mock the redirect method, and just trust that since it's only one line of code it can't really go wrong.
spyOn(whatever, 'redirect').andCallFake(function(){});
expect(whatever.redirect).toHaveBeenCalledWith('http:/my.expected/url');
This is sufficient for my purposes, and lets me validate the url called.
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