我是单元测试的新手,主要是从我找到的例子中学习。问题是,我看到了很多不同的模式,很难理解它们之间的差异。以及如何将这些模式组合到各种用例中。下面是一个这样的模式:
var $rootScope, $window, $location;
beforeEach(angular.mock.module('security.service', 'security/loginModal.tpl.html'));
beforeEach(inject(function(_$rootScope_, _$location_) {
$rootScope = _$rootScope_;
$location = _$location_;
}));
var service, queue;
beforeEach(inject(function($injector) {
service = $injector.get('security');
queue = $injector.get('securityRetryQueue');
}));
因此,从这种模式中,我发现应该使用下划线模式注入Angular核心服务/提供者,其他第三方依赖项或我自己的依赖项应该使用$ injector.get()模式完成。这有效吗?我注意到我可以使用Angular核心服务执行$ injector.get()并且它仍然可以工作所以也许它只是通过这种方式来实现吗?此外,' security / loginModal.tpl.html'是什么意思?在beforeEach(angular.mock.module('security.service', 'security/loginModal.tpl.html'));
?我知道它是一个添加到模板缓存的HTML模板,但是angular.mock.module做了什么呢?
我也看到过这种不太常见的模式,在上述逻辑中引发了一个小扳手:
beforeEach(inject(function($injector, _$location_) {
security = $injector.get('security');
$location = _$location_;
}));
如果我可以像注入$ location这样的注入回调添加服务,这似乎是一种更简单的引用依赖关系的方式。我为什么不这样做?
这是另一种模式:
beforeEach(function() {
module('security.service', function($provide) {
$provide.value('$window', $window = jasmine.createSpyObj('$window', ['addEventListener', 'postMessage', 'open']));
});
inject(function(security) {
service = security;
});
});
根据我的理解,这种模式的重点是初始化" security.service"带有模拟$窗口的模块。这是有道理的,但我如何使用以前的模式适应这种模式?即如何模拟&security / loginModal.tpl.html',如何注入我的Angular核心依赖项+我的其他依赖项?
最后,我可以在嵌套的描述中注入什么,它能阻止什么?假设我不能将模拟服务复制到我正在测试的模块中,这是否安全?那么我可以注入什么以及用例是什么?
如果有一个确定的AngularJS单元测试初始化文档源可以帮助回答这些问题,请指出。
答案 0 :(得分:2)
我已经知道Angular核心服务/提供程序应该注入下划线模式,其他第三方依赖项或我自己的依赖项应该使用$ injector.get()模式完成
您可以使用其中之一。 下划线模式只是一种方便的方法,可以避免与同名的局部变量发生冲突。请考虑以下
var $rootScope, myService, http; // these are local variables
beforeEach(inject(function(_$rootScope_, _myService_, $http) {
$rootScope = _$rootScope_; // underscores to avoid variable name conflict
myService = _myService_; // same here with your custom service
http = $http; // local variable is named differently to service
}));
如果我可以像注入$ location这样的注入回调添加服务,这似乎是一种更简单的引用依赖关系的方式。我为什么不这样做?
你应该:)
另外,
beforeEach(angular.mock.module('security.service', 'security/loginModal.tpl.html'));
中'security / loginModal.tpl.html'的重点是什么?
据我所知,除非你有一个具有该名称的实际模块,例如
angular.module('security/loginModal.tpl.html', [])
这会失败。 angular.mock.module
只应传递模块名称,实例或匿名初始化函数。
如何模拟'security / loginModal.tpl.html'
理想情况下,你不应该这样做。单元测试应测试代码的API ...交互点,通常由对象上可公开访问的方法和属性定义。
如果您只是想阻止Karma尝试通过HTTP加载模板(通常来自指令测试),您可以使用模板预处理器,如karma-ng-html2js-preprocessor
最后,我可以和不能在嵌套的描述和注入块中注入什么?假设我无法将模拟服务复制到我正在测试的模块中,这是否安全?那么我可以注入什么以及用例是什么?
您可以在任何地方(通常为beforeEach
和it
)运行angular.mock.inject
。模拟服务应仅在模块或匿名模块初始化函数中配置(如您的示例中$provide
和$window
),并且通常在您自己的模块之后(即“security.service”)以通过在注入器中替换它们来覆盖实际服务。运行inject()
后,您无法使用模拟回溯主动替换服务。