I have a situation where I want to add services inside a module, as I may not know what they are beforehand. From looking at the docs, it seems that the only way to do this (without global scope) is with Angular's $injector service. However, it seems that this service is not mockable, which makes sense as it is the way Angular itself gets the dependencies, which are still important even in testing.
Essentially, I am emulating NodeJS's passport module. I want to have something like a keychain, where you add or remove an account during runtime. So far, I have this:
angular.module('myModule').factory('accounts', function($injector) {
return {
add: function(name) {
if(!$injector.has(name) {
$log.warn('No Angular module with the name ' + name + ' exists. Aborting...');
return false;
}
else {
this.accounts[name] = $injector.get(name);
return true;
}
},
accounts: []
};
});
However, whenever I try to mock the $injector function in Jasmine, like this:
describe('accounts', {
var $injector;
var accounts;
beforeEach(function() {
$injector = {
has: jasmine.createSpy(),
get: jasmine.createSpy()
};
module(function($provide) {
$provide.value('$injector', $injector);
});
module('ngMock');
module('myModule');
inject(function(_accounts_) {
accounts = _accounts_;
});
});
describe('get an account', function() {
describe('that exists', function() {
beforeEach(function() {
$injector.has.and.returnValue(true);
});
it('should return true', function() {
expect(accounts.add('testAccount')).toEqual(true);
});
});
describe('that doesn't exist', function() {
beforeEach(function() {
$injector.has.and.returnValue(false);
});
it('should return true', function() {
expect(accounts.add('testAccount')).toEqual(false);
});
});
});
});
the 2nd test fails because the accounts service is calling the actual $injector service, and not the mock. I can confirm this by calling $injector.get or $injector.has during the test or in the service itself.
What should I do? There seems to be no other way to add new dependencies, but this is exactly what I want to do. Am I wrong? Is there in fact another way to do this, without using $injector?
Assuming I am right, and there is no other way to do what I want to do, how should I go about testing this function? I could just trust that the $injector service does its job, but I still want to mock it for the tests. I could manually add the dependencies during the inject function, but that doesn't replicate the actual behavior. I could just not test the function, but then I wouldn't be testing the function.
Aucun commentaire:
Enregistrer un commentaire