在测试中获取常量时,角度测试总是在$ logProvider上失败

时间:2014-10-09 02:30:54

标签: angularjs unit-testing karma-runner karma-jasmine

Angular测试的新手......使用1.3.0.rc0。为了开始,我尝试做一些简单的事情:获取我设置的常量的值。在config.js中,我有以下内容:

(function () {
    'use strict';

    var app = angular.module('app');

    // create app configuration
    var appConfig = {
        version = '0.0.1.0',
        debugMode = true
    };

    app.constant('config', appConfig);

    app.config([function ($logProvider, config) {
            // set the debugging setting of the app > same setting for the app
            if ($logProvider.debugEnabled) {
                $logProvider.debugEnabled(config.debugMode);
            }
        }]);
})();

我尝试了很多东西来编写我的测试(使用jasmine& karma),但我一直收到错误:

Error: [$injector:modulerr] Failed to instantiate module app due to: 
TypeError: 'undefined' is not an object (evaluating '$logProvider.debugEnabled').

我之前在angular-mocks.js文件中发现这是一个bug,但此后又被解决了。无论如何,无论我写的测试,它都不起作用。以下是我现在正在使用的内容,知道它存在问题。

'use strict';
describe('config.js', function () {
    var logProvider;

    beforeEach(module(inject(function ($log) {
        logProvider = $log;
    })));
    beforeEach(module('app', logProvider));

    it('should set the config constant to the app global configuration settings', function () {
        var $injector = angular.injector(['ng', 'app']);
        var settings = $injector.get('config');
        //var settings = inject(config);
        expect(settings.debugMode).toBe(true);
    });
});

我这样做了吗?如果是这样,是否有办法解决$ logProvider的测试问题?

1 个答案:

答案 0 :(得分:1)

有关模块如何在Angular中工作的知识有很多,特别是在使用ngMocks进行测试时。我会尽量简短。

总是通过调用module(来自ngMocks)一次(或多次)来构建测试运行的模块“cookbook”。

在任何module次调用中,您都有机会访问并隐藏先前定义的提供程序。

第一次在给定的测试路径中调用inject(来自ngMocks)时,模块“cookbook”将为该路径“烘焙”,并根据该“cookbook”中的食谱填充进样器。 / p>

module的后续调用无关紧要。您的表达式beforeEach(module('app', logProvider));执行得太晚(即使它执行了您想要的操作,也不会执行此操作)。

  

事实上,我很惊讶您没有收到错误:“错误:注射器已经创建,无法注册模块!”。

inject始终返回提供者创建的内容,而不是提供者本身。你的第一个beforeEach ...

beforeEach(module(inject(function ($log) {
    logProvider = $log;
})));

...实际上将logProvider设置为$log服务,而不是$logProvider

这有帮助吗?

以下是我即将开始的Ng测试课程的示例,该课程演示了如何访问提供程序(在本例中为$ logProvider)。它的灵感来自你的问题。

首先,config2常量(我已经有一个名为config的值:

// my sample application module definition is called 'basics'
var basics = angular.module('basics', []);

/* define 'config2' constant - which is available in Ng's config phase */
basics.constant('config2', {
    debugMode:  true
});

// use constant in config phase
basics.config(function ($logProvider, config2) {
    $logProvider.debugEnabled(config2.debugMode);
})

现在规范(使用Mocha和Chai):

describe('Basics - constant:', function() {
    'use strict';

    beforeEach(module('basics'));

    // other stuff

    describe("the $logProvider", function(){
        var configConstant;
        var $log;
        var $logProvider;

        beforeEach(module(
            // Could combine with module('basics') definition in outer describe
            // but only need it here in this describe

            // This module definition function has access to any previously defined provider
            // which in this case is any provider defined in ng, ngMocks, or basics
            function( _$logProvider_) {
                $logProvider = _$logProvider_;
            }
        ));

        // inject triggers injector creation; module definition now "baked"
        beforeEach(inject(function(config2, _$log_){
            configConstant = config2;
            $log = _$log_;
        }));

        it("is accessible via the module function", function(){
            expect($logProvider).to.exist;
        });

        it("is not the same as the log service", function(){
            expect($logProvider).not.to.equal($log);
        });

        it("has same debugEnabled value as config2.debugMode", function(){
            expect($logProvider.debugEnabled()).to.equal(configConstant.debugMode);
        });
    });

});