为什么针对angular-google-maps提供程序的此测试失败? [英] Why does this test for the angular-google-maps provider fail?

查看:184
本文介绍了为什么针对angular-google-maps提供程序的此测试失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试使用 angular-google-maps 的模块。它失败了因为 angular.mock.inject 找不到 uiGmapGoogleMapApiProvider

I'm trying to test a module that uses angular-google-maps. It is failing because angular.mock.inject cannot find uiGmapGoogleMapApiProvider:

Error: [$injector:unpr] Unknown provider: uiGmapGoogleMapApiProviderProvider <- uiGmapGoogleMapApiProvider

我无法弄清楚出了什么问题。这是简化的测试用例:

I can't figure out what is going wrong. Here is the reduced testcase:

'use strict';

describe('this spec', function() {
    beforeEach(module('uiGmapgoogle-maps'));

    it('tries to configure uiGmapGoogleMapApiProvider', inject(function(uiGmapGoogleMapApiProvider) {
        expect(uiGmapGoogleMapApiProvider.configure).toBeDefined();
    }));
});

整个事物可从 GitHub上。如果您发现问题,请在此处回答Stack Overflow。如果您还向GitHub存储库提交拉取请求,则会获得奖励。

The entire thing is available as a ready-to-run Angular project from GitHub. If you find the problem, please answer here on Stack Overflow. Bonus points if you also submit a pull request to the GitHub repository.

推荐答案

这里有两个陷阱相互影响,两者都没有与angular-google-maps有关。

Two pitfalls are at interplay here, neither of which has anything to do with angular-google-maps.

第一个陷阱在于服务和提供商之间的区别。文档声明服务,工厂,值和常量是提供者的特殊情况。对于像我这样的相对初学者,这似乎表明提供者和服务可以以相同的方式在任何地方依赖注入。然而,情况恰恰相反:在可以注入依赖关系的任何地方,您可以注入提供者或服务但不能同时注入两者。

The first pitfall lies in the distinction between services and providers. The documentation states that services, factories, values and constants are special cases of providers. To a relative beginner like me, this seems to suggest that providers and services can be dependency-injected anywhere in the same way. However, the opposite is true: in any place where dependencies can be injected, you can inject either providers or services but never both.

这种分歧的原因在于配置时间和运行时间之间的严格分离(请参阅模块文档)。提供程序在配置期间可用,而服务在运行时可用。配置时间结束后运行时间开始。 .config .provider 块在配置时执行,而大多数其他类型的块在运行时执行。提供者和服务定义之间的关系在以下代码片段中说明,改编自提供者文档

The reason for this divide lies in the strict separation between configuration time and run time (see module documentation). Providers are available during configuration time while services are available during run time. Run time starts after configuration time ends. .config and .provider blocks are executed at configuration time while most other types of blocks get executed at run time. The relation between provider and service definitions is illustrated in the following snippet of code, adapted from the provider documentation:

myModule.provider('myServiceProvider', ['injectedProvider', function MyServiceProvider(injectedProvider) {
    // configuration time code depending on injectedProvider

    this.$get = ["injectedService", function MyService(injectedService) {
        // run time code depending on injectedService
    }];

    // more configuration time code
}]);

如您所见,服务在提供商中定义。提供程序在配置时定义(外部块,函数MyServiceProvider ),并且可能依赖于其他提供程序。可以在运行时使用提供程序的。$ get 方法从提供程序中提取服务,该方法由内部块(函数MyService ),可能依赖于其他服务。提供者不能是服务的注入依赖项,反之亦然,但您可以将服务定义嵌套在上面的提供者定义中,以使其依赖于提供者间接。当您使用 angular.module(...)。service 块定义独立服务时,Angular会执行类似上面代码的操作。

As you can see, a service is defined within a provider. The provider is defined at configuration time (outer block, function MyServiceProvider) and may depend on other providers. The service can be extracted from the provider using the provider's .$get method, at run time, as defined by the inner block (function MyService), and may depend on other services. A provider cannot be an injected dependency of a service or vice versa, but you can nest a service definition inside a provider definition like above to make it depend on providers indirectly. When you define a "standalone" service using an angular.module(...).service block, Angular is doing something like the above code behind your back.

另一个陷阱是 angular.mock.inject ,这是注入来自我的问题中的单元测试,只能进行运行时注射。对于配置时间注入,您必须通过创建具有配置时间依赖性的新模块来执行真实的事情,即非模拟注入。这就是 mguimard 暗示的内容。 AndréEife发表了一篇简短的教程如何做到这一点,我通过回答底部的链接找到了我的另一个问题。

The other pitfall is that angular.mock.inject, which is the inject from the unit test in my question, can only do run time injections. For configuration time injections you have to do "the real thing", i.e. non-mocked injection, by creating a new module with configuration time dependencies. This is what mguimard hinted at. André Eife published a short tutorial on how to do this, which I found through a link at the bottom of an answer to my other question.

总之,这里的代码可以解决我的问题:

In conclusion, here is the code that would fix the problem in my question:

'use strict';

describe('this spec', function() {
    var gmapProvider;

    beforeEach(function() {
        angular.module('testAssist', ['uiGmapgoogle-maps'])
        .config(function(uiGmapGoogleMapApiProvider) {
            gmapProvider = uiGmapGoogleMapApiProvider;
        });
        module('testAssist');  // angular.mock.module
        inject();              // angular.mock.inject
    });

    it('tries to configure uiGmapGoogleMapApiProvider', function() {
        expect(gmapProvider.configure).toBeDefined();
    });
});

夹具中的'testAssist'模块( beforeEach )的存在的唯一目的是对 uiGmapGoogleMapApiProvider 具有配置时间依赖性,因此我可以捕获后者本地 gmapProvider 变量。随后对模块注入的调用是簿记技巧,以确保 config 'testAssist'被执行。感谢捕获,在测试用例中不需要进行注入( it ),我可以验证提供者是否有 configure 方法。请注意,第一个 angular.module 调用是常规模块定义,而第二个模块调用是来自模拟框架( angular.mock )。

The 'testAssist' module in the fixture (beforeEach) exists for the sole purpose of having a configuration time dependency on uiGmapGoogleMapApiProvider, so I can capture the latter in the local gmapProvider variable. The subsequent calls to module and inject are bookkeeping tricks to ensure that the config block of 'testAssist' gets executed. Thanks to the capture, no injection needs to be done within the testcase (it) and I can just verify that the provider has a configure method. Note that the first angular.module call is a regular module definition while the second module call is a special construct from the mocking framework (angular.mock).

我已将上述解决方案推送到 fix1分支

I have pushed the above solution to the fix1 branch on GitHub.

这篇关于为什么针对angular-google-maps提供程序的此测试失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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