【问题标题】:Angular Tests always fail on $logProvider when getting constants in tests在测试中获取常量时,Angular 测试总是在 $logProvider 上失败
【发布时间】:2014-10-09 02:30:53
【问题描述】:

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 文件中的一个错误,但已经解决了。无论如何,无论我写什么测试,它都不起作用。这就是我现在正在使用的东西,知道它存在问题。

'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 的测试问题?

【问题讨论】:

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


    【解决方案1】:

    关于模块在 Angular 中的工作方式有很多需要了解,尤其是在使用 ngMocks 进行测试时。我会尽量简短。

    总是首先调用module(来自ngMocks)一次(或多次)构建模块“cookbook”以进行测试运行。

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

    当您第一次在给定的测试路径中调用 inject(来自 ngMocks)时,模块“cookbook”会为该路径“烘焙”,并且注入器会根据该“cookbook”中的配方填充。

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

    事实上,我很惊讶你没有收到错误:“Error: Injector already created, can not register a module!”。

    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);
            });
        });
    
    });
    

    【讨论】:

    • BAM... 这成功了。我的问题是 (1) 了解注入的工作原理,(2) beforeEach() 如何与模块一起工作,以及 (3) 在源文件中 $logProvider 没有被正确注入。我不应该粘贴 $log 代码……那是在试图让它工作的过程中。谢谢!!!
    • @Ward...我对您的“...即将举行的 Ng 测试课程”非常感兴趣。有更多可用信息吗?谢谢!
    猜你喜欢
    • 2012-10-23
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多