这里有两个陷阱,它们都与 angular-google-maps 无关。
第一个陷阱在于服务和提供者之间的区别。该文档指出,服务、工厂、值和常量是提供者的特例。对于像我这样的相对初学者来说,这似乎表明提供者和服务可以以相同的方式在任何地方进行依赖注入。然而,情况正好相反:在任何可以注入依赖项的地方,您可以注入提供者或服务,但不能同时注入两者。
这种划分的原因在于配置时间和运行时间之间的严格分离(参见模块文档)。提供者在配置时可用,而服务在运行时可用。运行时间在配置时间结束后开始。.config
和.provider
块在配置时执行,而大多数其他类型的块在运行时执行。提供者和服务定义之间的关系在以下代码片段中说明,改编自提供者文档:
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
}]);
如您所见,服务是在提供者中定义的。提供者是在配置时定义的(外部块,function MyServiceProvider
),并且可能依赖于其他提供者。服务可以.$get
在运行时使用提供者的方法从提供者中提取,由内部块 ( function MyService
) 定义,并且可能依赖于其他服务。提供者不能是服务的注入依赖项,反之亦然,但您可以像上面一样将服务定义嵌套在提供者定义中,使其间接依赖于提供者。当您使用angular.module(...).service
块定义“独立”服务时,Angular 会在您背后执行类似上述代码的操作。
另一个陷阱是angular.mock.inject
,这是inject
我问题中单元测试的结果,只能进行运行时注入。对于配置时间注入,您必须通过创建具有配置时间依赖性的新模块来做“真实的事情”,即非模拟注入。这是mguimard 所暗示的。André Eife 发布了一个关于如何做到这一点的简短教程,我通过另一个问题的答案底部的链接找到了该教程。
总之,这是可以解决我的问题的代码:
'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
随后对module
and的调用inject
是簿记技巧,以确保执行config
块'testAssist'
。由于捕获,不需要在测试用例(it
)中进行注入,我可以验证提供者是否有configure
方法。请注意,第一次angular.module
调用是常规模块定义,而第二次module
调用是来自模拟框架 ( angular.mock
) 的特殊构造。
我已经将上述解决方案推送到 GitHub 上的fix1 分支。