我正在尝试开始使用Karma测试,将它们添加到现有的Angular应用程序中。
这是我的主要应用定义文件:
angular
.module('myApp', [
'ngRoute',
'moduleAdherence'
]);
这是我的控制器文件:
angular
.module('moduleAdherence', [])
.controller('AdherenceCtrl', ['$scope', function ($scope) {
$scope.awesomeThings = [1,2,3,4];
}]);
这是我对文件的第一次尝试:
describe('Controller: AdherenceCtrl', function () {
beforeEach(module('myApp'));
var MainCtrl,
scope;
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
MainCtrl = $controller('AdherenceCtrl', {
$scope: scope
});
}));
it('should attach a list of awesomeThings to the scope', function () {
expect(scope.awesomeThings.length).toBe(4);
});
});
当我尝试使用grunt test
运行时,它会失败,并显示以下错误:
Uncaught Error: [$injector:nomod] Module 'd3' is not available!
You either misspelled the module name or forgot to load it.
If registering a module ensure that you specify the dependencies
as the second argument.
http://errors.angularjs.org/1.2.0/$injector/nomod?p0=d3
at /Users/me/Dropbox/projects/myapp/app/bower_components/angular/angular.js:1498
我不明白这一点,因为这个控制器不使用D3。我在应用程序的其他地方使用D3,在指令中,但我没有在模块中注册它(我使用外部D3文件)。
为什么Karma会注意到D3?如果没有D3,它不应该能够测试这个控制器吗?
答案 0 :(得分:51)
在karma配置文件(karma.conf.js)中,您需要定义所有库。
等
// list of files / patterns to load in the browser
files: [
'app/lib/angular/angular.js',
'app/lib/angular-route/angular-route.js',
'test/lib/angular-mocks.js',
'app/app.js',
'app/controllers/*.js',
'app/services/*.js',
'app/*',
'test/spec/**/*.js'
],
答案 1 :(得分:34)
有一个类似的问题和我的解决方案(@danba评论的启发)是在files
中加载与完全相同的顺序中的脚本,因为它们在索引中加载。 HTML。
在我的案例中,像app/scripts/**/*.js
这样的全球化模式给业力造成了麻烦,因为业力不断出现错误。
也许不是最优雅的解决方案来复制所有脚本定义但最终工作,所以我的测试最终可以恢复运行。希望它有所帮助。
编辑:编辑此内容,因为今天我可能(以及希望)了解了这里出了什么问题。因此,当在一个文件中定义相同模块并在许多不同文件中使用时,Karma似乎不喜欢通配模式。让我们说你的文件夹结构是这样的:
假设在AuthService.js
中您拥有该文件夹中所有服务的模块定义,以便该文件以:
angular.module('myApp.services', [
'myApp.urls',
'ngCookies'
])
然后在所有其他文件中,您只需将其他服务附加到同一模块。在图片中tokenService.js
将以:
angular.module('myApp.services');
如果一切都保持这种状态,一切都可能奏效。但是,如果我有可能以相反的方式定义模块,那么模块定义不再是该文件夹的第一个文件,而是另一个Karma在AuthService
之后读取的模块定义抛出错误并拒绝完成测试。
解决方案可能是将模块定义放在自己的文件中,从下划线开始。最后,让所有兄弟姐妹文件都依赖于那个。所以上面的文件夹结构应该是:
另一个 - 可能更好 - 解决方案是使用公共后缀/扩展名标记模块所定义的文件,例如service.module.js
,而依赖它的文件可以像authService.js
一样正常命名, tokenService.js
。
此时的Karma配置将变为:
// list of files / patterns to load in the browser
files: [
'app/lib/angular/angular.js',
'test/lib/angular-mocks.js',
'app/app.js',
'app/**/*.module.js', // <-- first the module definitions...
'app/**/*.js', // <-- ..then all the other files
'test/spec/**/*.js'
],
这样,业力将首先加载模块定义,然后加载依赖于它们的文件。
答案 2 :(得分:1)
我也有同样的问题,在我的情况下出现了问题,因为每个模块有几个文件,这是一个不好的做法,因为我们可以指向未初始化的模块。解决了这个问题,每个模块只包含一个文件。
答案 3 :(得分:1)
始终将非缩小版角度加载到业力中。 它会显示错误并帮助您更好地找出要更改的内容。 在您的情况下,它是由业力加载的文件的顺序。
答案 4 :(得分:1)
检查index.html是否包含脚本标记之类的内容,如。
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5angular-resource.js"
您的所有Javascript文件都需要在您的karma.config.js
中答案 5 :(得分:1)
这是一个简单的解决方案,对我有用,基于@Nobita的上述解决方案#1,以及@ danba的评论。
在karma.conf.js中,显式加载必备文件,使其位于其余部分的模式上方:
files: [
...
'app/module.js',
'app/*.js'
]
Karma似乎并不介意该模式也匹配&quot; module.js&#39;。