我有一组分布在两个模块中的测试。
第一个模块有测试,并且对于它的依赖,我声明模拟测试它而不受其依赖模块的任何影响,如下所示:
beforeEach(function(){
angular.mock.module(function ($provide) {
$provide.value("mockServiceFromModule1", mockServiceFromModule1);
$provide.value("mockServiceFromModule2", mockServiceFromModule2);
});
angular.module('module1', []);
angular.module('module2', []);
angular.mock.module('moduleThatIAmTesting');
angular.mock.inject(function (_$rootScope_, _$q_, _$httpBackend_, ..., somethingFromTestModule) {
});
})
第二个模块有一系列测试,当我只运行它们时,所有测试都会通过。
beforeEach(function(){
angular.mock.module('module1');
angular.mock.inject(function (_$rootScope_, _$q_, _$httpBackend_, ..., somethingFromModule1) {
});
})
使用f(仅运行它们)运行时的两个测试都有效,但是当我运行整个测试套装时,我会收到错误,特别是关于模块声明或$httpBackend
。
我如何使茉莉花运行每个测试,好像它们是唯一的测试一样?
我似乎在每次测试时都在使用angular / modules / $ httpBackEnd,并且在开始新测试时会传播更改。
更新1 我有jsFiddle代表问题。 问题的结构是:
在JSFiddle上,关于$ httpBackend的错误没有任何要刷新的错误是因为对expectGet的请求永远不会被命中,并且由于之前加载的空模块而永远不会被命中
重要的是要注意,测试的ORDER是与JSFiddle中失败相关的唯一相关内容,并且它们通过相同的测试。
我当然可以制定一个测试命令并绕过它,但我的目标是找到一种方法来进行隔离测试,而不必担心其他测试副作用。
答案 0 :(得分:1)
您遇到的问题是由于$compileProvider
如何处理使用预先存在的名称注册的新指令的性质。
总之; 您没有覆盖旧指令,您正在创建具有相同名称的辅助指令。因此,原始实现会运行并尝试抓取baz.html
和$httpBackend
抛出,因为您尚未设置该调用的期望。
查看updated fiddle对original fiddle做出两次更改的ng-click。
parentModule
注入您的childModule
规范。不需要该行,这是您看到这些错误的部分原因。哦,angular.module
在测试之地是邪恶。尽量不要使用它。 以下是在以下场景中发生的事情的屏幕截图:
baz
的指令。 baz
的指令。 正如您可能想象的那样,为了让模块系统不要通过让人们覆盖每个指令来实现自己的操作 - $compileProvider
将只使用另一个指令 >同名。并且都将运行。
采用此article示例或此jsFiddle showing the decorator approach概述我们如何利用具有相同名称的多个指令。
请参阅下面附带的屏幕截图,了解您的情况。
71 到 73 行的代码是您可以实现我在答案开头提到的解决方案#2的地方。
baz
在testModule
的beforeEach中,替换以下内容:
$compileProvider.directive('baz', function () {
return {
restrict: 'E',
template: '{{value}}<div ng-transclude></div>',
controllerAs: 'bazController',
controller: function ($scope, fooService) {
$scope.value = 'baz' + fooService.get()
},
transclude: true
};
});
有了这个:
$provide.decorator('bazDirective', function ($delegate) {
var dir = $delegate[0];
dir.template = '{{value}}<div ng-transclude></div>';
dir.controller = function ($scope, fooService) {
$scope.value = 'baz' + fooService.get();
};
delete dir.templateUrl;
return $delegate;
});
<强> angular-module 强>
angular.module('parent', [])
的呼叫怎么样?除非您恰好使用http://jsfiddle.net/6oaxt61a/10/要点,否则不应在规范中致电
angular.module('name', [])
。即使这样,在测试的土地上也没有为你做太多。
仅使用.mock.module
或window.module
,否则您将终止与指定模块相关的即将推出的规范,因为您已经有效地杀死了模块定义其余的规范。
此外,baz
中parentModule
的{{1}}指令定义将自动在您的testModule
规范中提供,原因如下:
angular.module('parent', []).directive('baz', fn());
angular.module('child', ['parent']);
// In your test:
module('child'); // Will automatically fetch the modules that 'child' depend on.
因此,即使如果我们在您的规范中删除angular.module('parent', [])
调用,原始的baz
定义仍将加载。
因此,由于$compileProvider
支持具有相同名称的多个指令的性质,HTTP请求飞离,这是您的规范套件失败的原因。
另外,作为最后一点;您正在undefined
块中配置beforeEach
个模块。如果目标是配置测试模块,则说明错了。
语法如下:
mock.module('child', function ($compileProvider, /** etc **/) {
});
// Not this:
mock.module('child');
mock.module(function ($compileProvider, /** etc **/) {
});
这可以在我发布的截图中看到。被模拟的$$moduleName
定义的baz
属性为undefined
,而我假设您希望它为child
。