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