Let's say we want to mock a single service, i.e.
$location
. In case of internal angular's services we can use dedicated mocks, like the one described
here, but often something much simpler is enough. Let's say we have a service:
angular.module('myModule').factory('myService', function($location) {
return {
urlSize: $location.absUrl().length
}
});
and now we want to test it. Obviously all we need is just an object with a single function. In such case, for this test we can simply provide a new definition of the required service:
var url;
module('myModule');
module(function($provide) {
$provide.factory('$location', function() {
return {
absUrl: function () {return url}
}
})
});
and now our new
$location
is registered in angular's DI container and will be provided to all dependant services. Furthermore this test is a clear documentation that
myService
uses only this one single function of
$location
. There are no spies that obfuscate behaviour of tested code. How can we use this mock? It's a closure so in every test we can change the global variable
url
and the mocked
$location.absUrl()
will return this value. Now we can simply inject the service we want to test:
inject(function(myService) {
expect(myService.urlSize).toEqual(...);
});
Tested with angular 1.0.8 and 1.2.16