如何测试Angular模块的配置功能? [英] How to test the config function of an Angular module?

查看:120
本文介绍了如何测试Angular模块的配置功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Angular 模块 config 函数中定义了一些我要进行单元测试的设置代码。我不清楚我应该怎么做。下面是一个简化的测试用例,显示我是如何被卡住的:

I'm defining some setup code in the config function of an Angular module that I want to unit test. It is unclear to me how I should do this. Below is a simplified testcase that shows how I'm getting stuck:

'use strict';

angular.module('myModule', []).config(['$http', '$log', function($http, $log) {
    $http.get('/api/getkey').then(function success(response) {
        $log.log(response.data);
    });
}]);

describe('myModule', function() {
    it('logs a key obtained from XHR', inject(function($httpBackend) {
        $httpBackend.expectGET('/api/getkey').respond(200, '12345');
        angular.module('myModule');
        $httpBackend.flush();
    }));
});

这显然不是正确的方法,因为我收到以下错误:

This is clearly not the right way because I get the following error:

Error: No pending request to flush !

可以找到一个完整的,可立即运行的带有上述测试代码的Angular项目 。如果您知道如何处理此场景,请在此处回答Stack Overflow。如果您还向GitHub仓库提交拉取请求,则会获得奖励。

A complete, ready-to-run Angular project with the above testing code can be found on GitHub. If you know what to do with this scenario, please answer here on Stack Overflow. Bonus points if you also submit a pull request to the GitHub repo.

推荐答案

mzulch是正确的,指出服务无法注入 angular.module(...)。config 块。他还为您实际需要在模块初始化代码中使用服务的场景提供了正确的解决方案:使用 .run 块而不是 .config 阻止。他的回答非常适用于这种情况。

mzulch is right to point out that services cannot be injected in an angular.module(...).config block. He also provides the right solution for the scenario where you actually need to use services in module initialization code: use the .run block instead of the .config block. His answer works perfectly for this scenario.

如何为 .config 块编写单元测试的问题遗迹。让我们根据我的问题调整naieve代码到实际保证 .config 的情况。以下代码段注入提供程序依赖项而不是服务依赖项:

The question of how to write a unit test for the .config block remains. Let's adapt the naieve code from my question to a scenario where .config is actually warranted. The following snippet injects a provider dependency instead of a service dependency:

angular.module('myModule', []).config(['$httpProvider', function($httpProvider) {
    $httpProvider.useApplyAsync(true);
}]);

describe('myModule', function() {
    it('configures the $http service to combine response processing via $applyAsync', inject(function($httpProvider) {
        angular.module('myModule');
        expect($httpProvider.useApplyAsync()).toBeTruthy();
    }));
});

这一次,执行'myModule'是对的。然而,单元测试,与我的问题中的尝试类似,仍然是不正确的。现在Karma给了我以下错误:

This time, the implementation of 'myModule' is correct. The unit test however, which is analogous to the attempt in my question, is still incorrect. Now Karma gives me the following error:

Error: [$injector:unpr] Unknown provider: $httpProviderProvider <- $httpProvider

此隐密错误来自注入作为第二个参数传递给 it 。请注意提供商是如何结巴的。这是因为 inject 正在寻找 $ httpProvider 的提供者。我们称之为元提供者。 Angular框架中不存在这样的东西,但 inject 无论如何都在尝试它,因为它希望你只要求服务依赖。服务有提供者,例如, $ http $ httpProvider

This cryptical error is coming from the inject which is passed as the second argument to the it. Note how Provider is being stuttered. This is caused by the fact that inject is looking for the provider for $httpProvider. A "meta provider", as we may call it. Such things don't exist in the Angular framework, but inject is trying it anyway because it expects you to only ask for service dependencies. Services do have providers, for example, $http has $httpProvider.

所以注入(全名: angular.mock.inject ,这里全球可用)不是在测试用例中获取 $ httpProvider 的正确方法。正确的方法是使用模块 angular.mock.module )定义一个匿名模块配置函数我们可以捕获提供者的变量。这是有效的,因为提供商可以在配置时注入(参见链接位于 mzulch的答案的底部以及我自己的< a href =https://stackoverflow.com/a/39007140/1166087>回答我的其他问题,了解配置时间与运行时间的详细信息。它看起来像这样:

So inject (full name: angular.mock.inject, here available globally) is not the right way to get hold of $httpProvider in the testcase. The right way is to define an anonymous module configuration function using module (angular.mock.module) which closes over a variable in which we can capture the provider. This works because providers can be injected at configuration time (see the link at the bottom of mzulch's answer as well as my own answer to my other question for details on configuration time vs run time). It looks like this:

var $httpProvider;

beforeEach(function() {
    module(function(_$httpProvider_) {
        // this is a .config function
        $httpProvider = _$httpProvider_;
    });
    // after this I can use inject() to make the magic happen
});

我的naieve测试用例中的另一个错误是我正在尝试执行' myModule'的配置步骤是调用 angular.module('myModule')。出于测试用途的目的,我应该使用全局模块 angular.mock.module )代替最明智的地方这样做是在 beforeEach fixture中。总之,以下代码完成了这项工作:

Another mistake in my naieve testcase is that I'm trying to execute 'myModule's configuration steps by calling angular.module('myModule'). For testcase purposes, I should be using the global module (angular.mock.module) instead, and the wisest place to do so is in the beforeEach fixture. In conclusion, the following code does the job:

describe('myModule', function() {
    var $httpProvider;

    beforeEach(function() {
        module(function(_$httpProvider_) {
            $httpProvider = _$httpProvider_;
        });
        module('myModule');
    });

    it('configures the $http service to combine response processing via $applyAsync', function() {
        inject();  // enforces all the module config steps
        expect($httpProvider.useApplyAsync()).toBeTruthy();
    });
});

我选择将 inject()在我的测试用例的开头,但我也可以把它放在 beforeEach 的末尾。后一种方法的优点是我可以在一个地方写入 inject 的调用,而不需要在每个测试用例中重复它。这里实际采用的方法的优点是可以在以后的注射器中添加更多模块 beforeEach es甚至在单个测试用例中。

I opted to put the inject() at the start of my testcase, but I could also put it at the end of the beforeEach. The advantage of the latter approach would be that I can write the call to inject in one place and not need to repeat it in every testcase. The advantage of the approach actually taken here is that more modules can be added to the injector in later beforeEaches or even in individual testcases.

我将此替代解决方案推送到 GitHub

I pushed this alternative solution to a new branch on GitHub.

这篇关于如何测试Angular模块的配置功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆