【问题标题】:AngularJS + Jasmine unit test Error: [$injector:modulerr]AngularJS + Jasmine 单元测试错误:[$injector:modulerr]
【发布时间】:2016-02-08 17:46:21
【问题描述】:

我正在使用 Angular 和 jasmine 进行单元测试。运行测试时出现以下错误:

结果消息:错误:[$injector:modulerr] http://errors.angularjs.org/1.4.9/$injector/modulerr...

单元测试

/// <reference path="../Scripts/_references.js" />
/// <reference path="jasmine.js" />
/// <reference path="SampleController.js" />

describe('Controller Unit Test: ', function () {
    var scope, ctrl, $timeout;
    var someServiceMock;

    beforeEach(function () {
        module('app');
    });

    beforeEach(function () {
        someServiceMock = jasmine.createSpyObj('someService', ['someAsyncCall']);
        inject(function ($rootScope, $controller, $q, _$timeout_) {
            scope = $rootScope.$new();
            someServiceMock.someAsyncCall.andReturn($q.when('weee'));
            $timeout = _$timeout_;
            ctrl = $controller('SampleController', {
                $scope: scope,
                someService: someServiceMock
            });
        });
    });

    it('Controller exists', function () {
        expect(ctrl).toBeDefined();
    });
});

控制器

var app = angular.module('myApp', []);
app.controller('SampleController', function ($scope, someService) {

    //set some properties
    $scope.foo = 'foo';
    $scope.bar = 'bar';

    //add a simple function.
    $scope.test1 = function () {
        $scope.foo = $scope.foo + '!!!';
    };

    //set up a $watch.
    $scope.$watch('bar', function (v) {
        $scope.baz = v + 'baz';
    });

    //make a call to an injected service.
    $scope.test2 = function () {
        someService.someAsyncCall($scope.foo)
          .then(function (data) {
              $scope.fizz = data;
          });
    };
});

app.factory('someService', function ($timeout, $q) {
    return {

        // simple method to do something asynchronously.
        someAsyncCall: function (x) {
            var deferred = $q.defer();
            $timeout(function () {
                deferred.resolve(x + '_async');
            }, 100);
            return deferred.promise;
        }
    };
});

最后,我的参考文件:

/// <reference path="angular.min.js" />
/// <reference path="angular-mocks.js" />
/// <reference path="angular-animate.min.js" />
/// <reference path="angular-sanitize.min.js" />
/// <reference path="angular-route.min.js" />
/// <reference path="jquery-2.1.1.min.js" />
/// <reference path="jquery.unobtrusive-ajax.js" />
/// <reference path="jquery.unobtrusive-ajax.min.js" />
/// <reference path="jquery.validate.min.js" />
/// <reference path="ui-bootstrap-tpls-0.14.3.min.js" />
/// <reference path="modernizr-2.8.3.js" />

当我在测试中的注入函数中设置断点并运行调试模式时,它永远不会进入它。

【问题讨论】:

  • 您的单元测试文件顶部的引用列表中没有对控制器文件的引用。顺序也很重要,请确保它是最后引用的文件。
  • 对不起,它在里面,但我把它拿出来尝试一下。我仍然得到同样的错误

标签: angularjs unit-testing jasmine


【解决方案1】:

尝试像这样修改您的测试代码,我还冒昧地修改了您的结构,这样您的测试可能会更有效率。对于较小的控制器/测试,这无关紧要,但对于更复杂的功能,重置测试集的能力使这更容易。

第一个beforeEach$injector 注入到函数中,您可以使用它来获取参考。这可以在 describe 主函数中完成,因为它们可能不会改变。

第二个beforeEach 我已经嵌套在一个新的describe 函数中。然后,您可以创建一组批处理测试,其中每个it 都保证是一个新的/新的控制器实例。

如果$injector 为空或未定义,则表示脚本未加载或加载顺序错误。为了更好地解决这个问题,您需要查看注入失败的原因,因为 Angular 尚未意识到这一点,在这种情况下,请像您开始在帖子顶部一样使用完整的消息/URL 进行评论,然后我们可以将参考顺序正确。

控制器文件

/// <reference path="jquery-2.1.1.min.js" />
/// <reference path="angular.min.js" />
... rest of your code

单元测试文件

/// <chutzpah_reference path="angular.min.js"/>
/// <chutzpah_reference path="angular-mocks.js"/>
// you might need additional chutzpah_reference but it really depends on your chutzpah configuration found in chutzpah.json
/// <reference path="jquery-2.1.1.min.js" />
/// <reference path="angular.min.js" />
/// <reference path="angular-mocks.js" />
/// <reference path="jasmine.js" />
/// <reference path="SampleController.js" />

describe('Controller Unit Test: ', function () {
    var $rootScope;  //, $timeout;
    var someServiceMock;

    beforeEach(function () {
        angular.mock.module("app"); // mock your module
    });

    // setup
    beforeEach(inject(function ($injector) {
        someServiceMock = jasmine.createSpyObj('someService', ['someAsyncCall']);
        someServiceMock.someAsyncCall.andReturn($q.when('weee'));

        var $rootScope = $injector.get("$rootScope");
        // $timeout = $injector.get("$timeout"); // not used anywhere that I can see
    }));

    describe('this will executes initial some set of tests on your controller', () => {
        var scope;
        var ctrl;
        beforeEach(inject(function ($controller) {
            scope = $rootScope.$new();
            ctrl = $controller('SampleController', {
                $scope: scope,
                someService: someServiceMock});
        }));

        it('Controller exists', function () {
            expect(scope).toBeDefined();
            expect(ctrl).toBeDefined();
        });
    });
});

编辑 1

更改了参考。添加了角度模拟调用。

【讨论】:

  • 我把它复制到另一个测试文件中,同样的错误。当我断点并将鼠标悬停在 it() 中的范围和 ctrl 变量上时,它们是未定义的。无论出于何种原因,代码永远不会进入注入功能块。
  • @steveareeno - 我更新了代码。您能否相应地更新您的参考资料并调用模拟模块?
  • 我试过了,甚至完全从控制器和单元测试中删除了服务引用。如果我在 VS 2012 中使用 chutzpah 会有什么不同吗?
  • @steveareeno - 是的,这会带来很大的不同。您将需要包含 chutzpah 引用或确保 chutzpah 知道所有相应的文件,以便它可以加载所有内容。您可能应该将其包含在原始帖子中。给我一点,我会看看我是否可以相应地更新参考资料。
  • @steveareeno - 如果您在单元测试文件中需要chutzpah_reference 引用,很大程度上取决于您在chutzpah.json 中找到的胆大妄为的配置和您的文件布局。尽管注入不起作用,这可能是一个原因,因为 chutzpah 从不复制它正在执行的单元测试的引用。我已经更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 1970-01-01
  • 2014-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多