我希望重用我的模拟,而不必在每个将它们作为依赖项的单元测试中进行设置。但是我很难弄清楚如何正确注射它们。
这是我进行单元测试设置的尝试,由于ConfigServiceMockProvider不存在,因此当然失败了。
describe('LoginService tests', function () {
var LoginService;
beforeEach(module('mocks'));
beforeEach(module('services.loginService', function ($provide, _ConfigServiceMock_) {
$provide.value("ConfigService", _ConfigServiceMock_);
/* instead of having to type e.g. everywhere ConfigService is used
* $provide.value("ConfigService", { 'foobar': function(){} });
*/
});
beforeEach(inject(function (_LoginService_) {
LoginService = _LoginService_;
});
}
ConfigServiceMock
angular.module('mocks').service('ConfigServiceMock', function() {
this.init = function(){};
this.getValue = function(){};
}
我意识到我可能可以让ConfigServiceMock.js创建一个全局窗口对象,从而不需要像这样加载它。但是我觉得应该有更好的方法。
最佳答案
尝试这样的事情:
describe('Using externally defined mock', function() {
var ConfigServiceMock;
beforeEach(module('mocks'));
beforeEach(module('services.configService', function($provide) {
$provide.factory('ConfigService', function() {return ConfigServiceMock;});
}));
beforeEach(module('services.loginService'));
beforeEach(inject(function (_ConfigServiceMock_) {
ConfigServiceMock = _ConfigServiceMock_;
}));
// Do not combine this call with the one above
beforeEach(inject(function (_LoginService_) {
LoginService = _LoginService_;
}));
it('should have been given the mock', function() {
expect(ConfigServiceMock).toBeDefined('The mock should have been defined');
expect(LoginService.injectedService).toBeDefined('Something should have been injected');
expect(LoginService.injectedService).toBe(ConfigServiceMock, 'The thing injected should be the mock');
});
});
根据this answer,您必须将所有呼叫
module
放在所有呼叫inject
之前。这引入了一个catch 22的问题,因为您必须在规范中具有对ConfigServiceMock的引用(通过
inject
),然后才能在LoginService上进行设置(在module
调用中完成)解决方法是将角度工厂函数设置为ConfigService依赖项。这将导致angular延迟加载服务,届时您将收到对ConfigServiceMock的引用。