AngularJS测试,找不到我的控制器

时间:2014-02-13 13:45:52

标签: javascript angularjs unit-testing

我遇到了测试控制器的问题。我动态加载它们(延迟加载,见后),所以我这样写了:

angular.module('myApp').controllerProvider.register('DashboardCtrl', [
    '$scope', function ($scope) {
        $scope.foo = 'bar';
    }
]);

我将这个模块初始化为:

var app = angular.module('myApp', [
    'ngRoute',
    'ngCookies',
    'ngResource',
    'ngSanitize',
    'ui.router'
]);

app.run([
    '$rootScope', '$state', '$stateParams',
    function ($rootScope, $state, $stateParams) {
        $rootScope.$state = $state;
        $rootScope.$stateParams = $stateParams;
    }
]);

app.config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
    app.stateProvider = $stateProvider;
    app.routeProvider = $urlRouterProvider;
    app.controllerProvider = $controllerProvider;
    app.compileProvider = $compileProvider;
    app.filterProvider = $filterProvider;
    app.provide = $provide;

    $urlRouterProvider.otherwise('/');

    $stateProvider
        .state('dashboard', {
            url         : '/',
            templateUrl : 'views/dashboard.html',
            controller  : 'DashboardCtrl',
            resolve     : {
                deps : function ($q, $rootScope) {
                    var deferred = $q.defer();

                    curl('scripts/controllers/dashboard.js')
                        .then(function () {
                            $rootScope.$apply(function () {
                                deferred.resolve({});
                            });
                        });

                    return deferred.promise;
                }
            }
        });
});

有效。方法在那里描述:http://ify.io/lazy-loading-in-angularjs/

但是当我想测试时,我每次都会得到错误:错误:[ng:areq]参数'DashboardCtrl'不是函数,未定义

我的测试脚本:

describe('Controller: DashboardCtrl', function () {
    'use strict';

    var DashboardCtrl,
        scope;

    // load the controller's module
    beforeEach(function () {
        var app = angular.module('cellierApp', [
            'ngRoute',
            'ngCookies',
            'ngResource',
            'ngSanitize',
            'ui.router'
        ]);

        app.run([
            '$rootScope', '$state', '$stateParams',
            function ($rootScope, $state, $stateParams) {
                $rootScope.$state = $state;
                $rootScope.$stateParams = $stateParams;
            }
        ]);

        app.config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
            app.stateProvider = $stateProvider;
            app.routeProvider = $urlRouterProvider;
            app.controllerProvider = $controllerProvider;
            app.compileProvider = $compileProvider;
            app.filterProvider = $filterProvider;
            app.provide = $provide;
        });

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

    it('should attach a list of awesomeThings to the scope', function () {
        expect(scope.foo).toBeDefined();
        expect(scope.foo).toBe('bar');
    });
});

我不知道我做错了什么。有人知道吗?提前致谢

3 个答案:

答案 0 :(得分:2)

我不确定Karma是否支持Script.js加载,但肯定它支持Require.js。

既然您已经按照该教程进行了操作,那么您是否已经查看了他在github上提供的最终示例(它还包含单元测试)?这个想法是你可以将所有内容转换为使用Require.js而不是Script.js,并使用带有karma-requirejs的Karma进行测试。

虽然不太难,但有很多变化。我不会在这里发布工作代码,但我建议您阅读以下内容: http://ify.io/unit-testing-lazily-loaded-angularjs-artefacts/http://karma-runner.github.io/0.8/plus/RequireJS.html

我无法链接最后一个示例,因为我没有声誉,但它位于您已链接的教程的底部。

  

要查看使用RequireJS的异步模块定义的可运行示例,请查看示例应用程序。"

答案 1 :(得分:1)

您不会加载模块,但会覆盖此代码段中的角度模块:

 var app = angular.module('cellierApp', [
    'ngRoute',
    'ngCookies',
    'ngResource',
    'ngSanitize',
    'ui.router'
  ]);

正确的电话会是

beforeEach(function() {
    // the module to be tested
    module('cellierApp');
});

此外,应用程序的var声明是非常糟糕的imo。你有角度作为容器,使用它,不要无缘无故地在全局闭包上创建对象。改变这个:

var app = angular.module('myApp', [
    'ngRoute',
    'ngCookies',
    'ngResource',
    'ngSanitize',
    'ui.router'
]);

app.run...

要:

angular.module('myApp', [
        'ngRoute',
        'ngCookies',
        'ngResource',
        'ngSanitize',
        'ui.router'
    ])
.config([...

.run([....

单元测试本身可以简化:

describe('Controller: DashboardCtrl', function() {
    'use strict';

    var scope;

    // load the controller's module
    beforeEach(function() {
        module('cellierApp');
    });

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

    it('should attach a list of awesomeThings to the scope', function() {
        expect(scope.foo).toBeDefined();
        expect(scope.foo).toBe('bar');
    });
});

答案 2 :(得分:0)

在您的测试中,您没有注册控制器

将您的代码用于在测试中创建控制器

app.controllerProvider.register('DashboardCtrl', [
    '$scope', function ($scope) {
        $scope.foo = 'bar';
    }
]);

但是根据您的测试设置,您的应用和控制器文件应该通过您的测试系统加载,您应该使用

beforeEach(module('cellierApp'));

而不是直接在测试中创建应用