Mocking AngularJS services in unit test

When unit testing controllers in AngularJS, there are good mechanisms in place for mocking injected services, as such:

var controller;
var myServiceMock = {
	myServiceMethod: sinon.stub()
};

module('myApp');
inject(function($rootScope, $controller) {
    var scope = $rootScope.$new();
    var controller = $controller('MyController', 
    	{ $scope: scope, MyService: myServiceMock });
    }
}

So now we've created a mock of MyService, and fed it into MyController, keeping the unit test isolated to testing the controller and not the service.

But what if you have a service that depends on other services? There's no $service service that works like $controller that lets you directly inject a mock version of a service... There is however a $provide service that you can use to indirectly control the services that are injected into other services. So to unit test a service (MyOtherService) that depends on another service (MyService), do this:

var myOtherService;
var myServiceMock = {
    myServiceMethod: sinon.stub()
};

module('myApp', function($provide) { 
	$provide.factory("MyService", function() { return myServiceMock; });
}
inject(function($rootScope, MyOtherService) {
	var myOtherService = MyOtherService;
}

The provide service will now inject the mocked version of MyService into MyOtherService, so you can unit test it without the actual MyService being called.

comments powered by Disqus
Find me on Mastodon