I am testing a service 1 depending on another service B. The correct way to usually do it is to use the $provide
object before injecting A. However, I have two constraints :
The problem is, so far (I was testing controllers), I to be able to access the service B from my test, I need to inject it. But to mock it in the $provide
I need to already have access to it in my test, which poses a problem, since the $provide
needs to be used before any inject()
. Here is my test:
describe('viewsListService', function() {
var viewList,
queryDeferred,
mockViews,
$scope;
beforeEach(module('BoardMocks'));
beforeEach(module('Board'));
beforeEach(inject(function(mockViewsService) {
var query = {};
mockViewsService.init({}, query);
queryDeferred = query.deferred;
mockViews = mockViewsService.mock;
}));
beforeEach(function() {
angular.mock.module('Board', function ($provide) {
$provide.value('Views', mockViews);
});
});
beforeEach(inject(function(viewsListService, $rootScope) {
$scope = $rootScope.$new();
viewList = viewsListService;
// Initialisation of the viewsListService
viewList.init();
queryDeferred.resolve([1]);
$scope.$digest();
}));
describe('getAllViews', function() {
var allViews;
beforeEach(function() {
allViews = viewList.getAllViews();
});
it('should return all the views', function() {
expect(allViews.length).toBe(1);
});
});
});
This gives me an Error: Injector already created, can not register a module!
, pointing to the angular.mock.module call.
I moved my mock service to another module, thinking that perhaps it would solve the problem, wondering if the injector was specific to a module, but it doesn't seem to be (moving the beforeEach(module('Board'));
after the first inject()
doesn't fix the problem.
Do you have any idea to make it work, while keeping the mock in external file (I am fine with not registering it as an Angular Service, but just to a normal object, if it can solve this).
After a lot of looking around, I found an answer by Valentyn Shybanov that explain how to do this. It is quite simple in fact. I'll leave it here for other losts souls.
Actually in AngularJS Dependency Injection uses the 'last wins' rule. So you can define your service in your test just after including your module and dependencies, and then when service A that you're testing will request service B using DI, AngularJS will give mocked version of service B.
So if you want to mock the "Views" service. You create a "BoardMocks" module that contains a "Views" service. If "BoardMocks" is included after "Board", the mocked "Views" service will be used during the tests.
See the original answer here : Injecting dependent services when unit testing AngularJS services
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