【问题标题】:Angular mock fails to inject my module dependenciesAngular mock 无法注入我的模块依赖项
【发布时间】:2014-04-30 07:32:39
【问题描述】:

我想为我的应用程序 fooApp 测试一个 Angular 控制器,定义如下:

var fooApp = angular.module('fooApp', [ 'ngRoute', 'ngAnimate', 'hmTouchEvents' ]);
...

定义了控制器MainCtrl

"use strict";

fooApp.controller('MainCtrl', function ($scope, $rootScope, fooService) {
    ...
}

所以我测试了几种创建测试的方法,比如这个:

'use strict';

describe('MainController test', function () {

    var scope;
    var controller;

    beforeEach(function () {
            angular.mock.module('ngRoute', []);
            angular.mock.module('ngAnimate', []);
            angular.mock.module('hmTouchEvents', []);
            angular.module('cwfApp', [ 'ngRoute', 'ngAnimate', 'hmTouchEvents' ]);

            angular.mock.inject(function ($rootScope, $controller) {
                scope = $rootScope.$new();
                controller = $controller('MainCtrl', {
                    $scope: scope
                });
            });
        });

        it('should display a list', function () {
            console.log('-------------- Run Test 1 | ' + scope);
            expect(scope.currentStep).toBe(1);
        });

});

结果:

        Error: [$injector:modulerr] http://errors.angularjs.org/1.2.16-build.64+sha.245de33/$injector/modulerr?p0=undefined&p1=Error%3A%20%5Bng%3Aareq%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.2.16-build.64%2Bsha.245de33%2Fng%2Fareq%3Fp0%3Dfn%26p1%3Dnot%2520a%2520function%252C%2520got%2520undefined%0A%20%20%20%20at%20Error%20(%3Canonymous%3E)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A6%3A471%0A%20%20%20%20at%20wb%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A18%3A360)%0A%20%20%20%20at%20Qa%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A18%3A447)%0A%20%20%20%20at%20nc%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A31%3A191)%0A%20%20%20%20at%20Object.d%20%5Bas%20invoke%5D%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A33%3A176)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A32%3A254%0A%20%20%20%20at%20Array.forEach%20(native)%0A%20%20%20%20at%20r%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A7%3A298)%0A%20%20%20%20at%20e%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A32%3A9)
        at Error (<anonymous>)
        at d:/dev/foo/app/bower_components/angular/angular.min.js:6:471
        at d:/dev/foo/app/bower_components/angular/angular.min.js:32:400
        at Array.forEach (native)
        at r (d:/dev/foo/app/bower_components/angular/angular.min.js:7:298)
        at e (d:/dev/foo/app/bower_components/angular/angular.min.js:32:9)
        at Object.$b [as injector] (d:/dev/foo/app/bower_components/angular/angular.min.js:35:98)
        at workFn (d:/dev/foo/app/bower_components/angular-mocks/angular-mocks.js:2142:52)
        at Object.window.inject.angular.mock.inject [as inject] (d:/dev/foo/app/bower_components/angular-mocks/angular-mocks.js:2133:37)
        at null.<anonymous> (d:/dev/foo/test/jasmine/todo.test.js:15:22)
    TypeError: Cannot read property 'currentStep' of undefined
        at null.<anonymous> (d:/dev/foo/test/jasmine/todo.test.js:25:21)
Chrome 31.0.1650 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.023 secs / 0.015 secs)        

我也用beforeEach(angular.mock.module('cwfApp'));测试过(而不是前面代码中的第一个beforeEach),但错误几乎一样。

关于我的 karma.conf.js 文件,我设置了这个文件列表:

    files: [
        'app/bower_components/angular/angular.min.js',
        'app/bower_components/angular-route/angular-route.min.js',
        'app/bower_components/hammerjs/hammer.min.js',
        'app/bower_components/angular-hammer/angular-hammer.js',
        'app/bower_components/angular-mocks/angular-mocks.js',

        'app/js/foo-application.js',
        'app/js/foo-controllers.js',
        'app/js/foo-services.js',
        'app/js/foo-router.js',

        'test/jasmine/*.js'
    ],

注入似乎失败了,但我真的不明白我的配置中缺少什么或错误。上面的stacktrace并没有给出太多的解释……

有什么想法吗?

我使用的是 Angular 1.2.8。

问候

编辑,使用@Engineer提供的代码:

beforeEach(angular.mock.module('fooApp'));

beforeEach(angular.mock.inject(function($rootScope, $controller) {
    scope = $rootScope.$new();
    controller = $controller('MainCtrl', {
        $scope: scope
    });
}));

it('should display a list', function () {
    console.log('-------------- Run Test 1 | ' + scope);
    expect(scope.currentStep).toBe(1);
});

错误几乎一样:

    Error: [$injector:modulerr] http://errors.angularjs.org/1.2.16-build.64+sha.245de33/$injector/modulerr?p0=cwfApp&p1=Error%3A%20%5B%24injector%3Amodulerr%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.2.16-build.64%2Bsha.245de33%2F%24injector%2Fmodulerr%3Fp0%3DngAnimate%26p1%3DError%253A%2520%255B%2524injector%253Anomod%255D%2520http%253A%252F%252Ferrors.angularjs.org%252F1.2.16-build.64%252Bsha.245de33%252F%2524injector%252Fnomod%253Fp0%253DngAnimate%250A%2520%2520%2520%2520at%2520Error%2520(%253Canonymous%253E)%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A9876%252Fbase%252Fapp%252Fbower_components%252Fangular%252Fangular.min.js%253F5961971009303638e9ad386869316e8c83f67e56%253A6%253A471%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A9876%252Fbase%252Fapp%252Fbower_components%252Fangular%252Fangular.min.js%253F5961971009303638e9ad386869316e8c83f67e56%253A20%253A260%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A9876%252Fbase%252Fapp%252Fbower_components%252Fangular%252Fangular.min.js%253F5961971009303638e9ad386869316e8c83f67e56%253A21%253A262%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A9876%252Fbase%252Fapp%252Fbower_components%252Fangular%252Fangular.min.js%253F5961971009303638e9ad386869316e8c83f67e56%253A32%253A69%250A%2520%2520%2520%2520at%2520Array.forEach%2520(native)%250A%2520%2520%2520%2520at%2520r%2520(http%253A%252F%252Flocalhost%253A9876%252Fbase%252Fapp%252Fbower_components%252Fangular%252Fangular.min.js%253F5961971009303638e9ad386869316e8c83f67e56%253A7%253A298)%250A%2520%2520%2520%2520at%2520e%2520(http%253A%252F%252Flocalhost%253A9876%252Fbase%252Fapp%252Fbower_components%252Fangular%252Fangular.min.js%253F5961971009303638e9ad386869316e8c83f67e56%253A32%253A9)%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A9876%252Fbase%252Fapp%252Fbower_components%252Fangular%252Fangular.min.js%253F5961971009303638e9ad386869316e8c83f67e56%253A32%253A86%250A%2520%2520%2520%2520at%2520Array.forEach%2520(native)%0A%20%20%20%20at%20Error%20(%3Canonymous%3E)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A6%3A471%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A32%3A400%0A%20%20%20%20at%20Array.forEach%20(native)%0A%20%20%20%20at%20r%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A7%3A298)%0A%20%20%20%20at%20e%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A32%3A9)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A32%3A86%0A%20%20%20%20at%20Array.forEach%20(native)%0A%20%20%20%20at%20r%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A7%3A298)%0A%20%20%20%20at%20e%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fapp%2Fbower_components%2Fangular%2Fangular.min.js%3F5961971009303638e9ad386869316e8c83f67e56%3A32%3A9)
        at Error (<anonymous>)
        at d:/dev/foo/app/bower_components/angular/angular.min.js:6:471
        at d:/dev/foo/app/bower_components/angular/angular.min.js:32:400
        at Array.forEach (native)
        at r (d:/dev/foo/app/bower_components/angular/angular.min.js:7:298)
        at e (d:/dev/foo/app/bower_components/angular/angular.min.js:32:9)
        at Object.$b [as injector] (d:/dev/foo/app/bower_components/angular/angular.min.js:35:98)
        at workFn (d:/dev/foo/app/bower_components/angular-mocks/angular-mocks.js:2142:52)
    TypeError: Cannot read property 'currentStep' of undefined
        at null.<anonymous> (d:/dev/foo/test/jasmine/todo.test.js:20:21)

我将尝试创建一个小提琴来重现我的问题...

【问题讨论】:

    标签: angularjs jasmine karma-runner karma-jasmine angular-mock


    【解决方案1】:

    我的问题实际上是由于karma.conf.js 中的一个小错误。事实上,我的应用程序定义如下:

    var fooApp = angular.module('fooApp', [ 'ngRoute', 'ngAnimate', 'hmTouchEvents' ]);
    

    而我的karma.conf.js 会加载以下脚本:

    files: [
        'app/bower_components/angular/angular.min.js',
        'app/bower_components/angular-route/angular-route.min.js',
        'app/bower_components/hammerjs/hammer.min.js',
        'app/bower_components/angular-hammer/angular-hammer.js',
        'app/bower_components/angular-mocks/angular-mocks.js',
    
        'app/js/foo-application.js',
        'app/js/foo-controllers.js',
        'app/js/foo-services.js',
        'app/js/foo-router.js',
    
        'test/jasmine/*.js'
    ], ...
    

    但未加载模块 ngAnimate。所以我只是添加了那行:

        'app/bower_components/angular-animate/angular-animate.min.js',
    

    它有效!

    【讨论】:

      【解决方案2】:

      您正在重新定义测试中的 fooApp 模块。

      您需要在测试代码中使用 Angular 加载它,如下所示:

      angular.mock.module('ngRoute', 'ngAnimate', 'hmTouchEvents', 'fooApp');
      

      【讨论】:

      • 你好。谢谢。抱歉,由于对我的代码进行了许多测试,这只是复制/粘贴的错误。我已经编辑了代码测试和堆栈错误。
      • 你把我弄丢了......你能创造一个重现问题的小提琴吗?你能期望(控制器).toBeDefined(); ?
      • 我会尝试创建这样的小提琴。我想知道我是否没有遗漏我的控制器所需的 fooService 的某些内容,但没有被模拟/创建...
      • 没有传递给$controller的参数是由Angular定期注入的,即Angular注入一个真实控制器的实例
      • 终于找到问题了(参考我的回答)。我忘了在karma.conf.js 中添加angular-animate
      【解决方案3】:

      试试这样:

      describe('MainController test', function () {
          var scope;
          var controller;
      
          beforeEach(angular.mock.module('fooApp'));
          beforeEach(angular.mock.inject(function($rootScope, $controller) {
              scope = $rootScope.$new();
              controller = $controller('MainCtrl', {
                  $scope: scope
              });
          });
          it('should display a list', function () {
              console.log('-------------- Run Test 1 | ' + scope);
              expect(scope.currentStep).toBe(1);
          });
      });
      

      你需要理解的是,如果你声明了一些模块及其依赖项(如angular.module('fooApp', [ 'ngRoute', 'ngAnimate', 'hmTouchEvents' ])),当你在测试中注入模块(fooApp)时,你不需要注入依赖项模块。

      【讨论】:

      • 感谢您提供有关注入依赖项的信息。但是,尝试该代码并没有帮助我(参见我编辑的帖子)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-02
      • 2011-09-22
      • 2021-04-13
      相关资源
      最近更新 更多