在Angular应用程序的Karma测试文件中包含依赖项?

时间:2013-11-21 21:58:13

标签: javascript angularjs karma-runner

我正在尝试开始使用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,它不应该能够测试这个控制器吗?

6 个答案:

答案 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似乎不喜欢通配模式。让我们说你的文件夹结构是这样的:

risky folder structure

假设在AuthService.js中您拥有该文件夹中所有服务的模块定义,以便该文件以:

开头
angular.module('myApp.services', [
  'myApp.urls',
  'ngCookies'
])

然后在所有其他文件中,您只需将其他服务附加到同一模块。在图片中tokenService.js将以:

开头
angular.module('myApp.services');

如果一切都保持这种状态,一切都可能奏效。但是,如果我有可能以相反的方式定义模块,那么模块定义不再是该文件夹的第一个文件,而是另一个Karma在AuthService之后读取的模块定义抛出错误并拒绝完成测试。

解决方案1 ​​

解决方案可能是将模块定义放在自己的文件中,从下划线开始。最后,让所有兄弟姐妹文件都依赖于那个。所以上面的文件夹结构应该是:

safer folder structure

解决方案2

另一个 - 可能更好 - 解决方案是使用公共后缀/扩展名标记模块所定义的文件,例如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;。