我正在尝试测试使用angular-google-maps
的模块。它失败了,因为angular.mock.inject
找不到uiGmapGoogleMapApiProvider
:
Error: [$injector:unpr] Unknown provider: uiGmapGoogleMapApiProviderProvider <- uiGmapGoogleMapApiProvider
我无法弄清楚出了什么问题。这是简化的测试用例:
'use strict';
describe('this spec', function() {
beforeEach(module('uiGmapgoogle-maps'));
it('tries to configure uiGmapGoogleMapApiProvider', inject(function(uiGmapGoogleMapApiProvider) {
expect(uiGmapGoogleMapApiProvider.configure).toBeDefined();
}));
});
整个内容可以作为GitHub中准备好运行的Angular项目提供。如果您发现问题,请在此处回答Stack Overflow。如果您还向GitHub存储库提交拉取请求,则会获得奖励。
答案 0 :(得分:2)
这里有两个陷阱,这两个陷阱都没有与angular-google-maps有任何关系。
第一个陷阱在于服务和提供者之间的区别。服务,工厂,值和常量的文档states是提供者的特例。对于像我这样的相对初学者,这似乎表明提供者和服务可以以相同的方式在任何地方依赖注入。然而,情况正好相反:在可以注入依赖关系的任何地方,您可以注入提供者或服务,但不能同时注入。
这种分歧的原因在于配置时间和运行时间之间的严格分离(参见module documentation)。提供程序在配置期间可用,而服务在运行时可用。配置时间结束后运行时间开始。 .config
和.provider
块在配置时执行,而大多数其他类型的块在运行时执行。提供者和服务定义之间的关系在以下代码片段中说明,改编自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
}]);
如您所见,服务在提供商中定义。提供程序在配置时定义(外部块,function MyServiceProvider
),并且可能依赖于其他提供程序。可以在运行时使用提供程序的.$get
方法从提供程序中提取服务,如内部块(function MyService
)所定义,并且可以依赖于其他服务。提供者不能是服务的注入依赖项,反之亦然,但您可以将服务定义嵌套在上面的提供者定义中,以使其依赖于提供者间接。当您使用angular.module(...).service
块定义“独立”服务时,Angular会执行类似上面代码的操作。
另一个缺陷是angular.mock.inject
,即我问题中单元测试的inject
,只能进行运行时注射。对于配置时间注入,您必须通过创建具有配置时间依赖性的新模块来执行“真实的事情”,即非模拟注入。这是mguimard暗示的内容。 AndréEife发表了关于如何做到这一点的简短tutorial,我通过answer底部的链接找到了我的另一个问题。
总之,以下是解决问题的代码:
'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
具有配置时间依赖性,因此我可以在本地{{1}中捕获后者变量。随后对gmapProvider
和module
的调用是簿记技巧,以确保inject
config
块被执行。由于捕获,在测试用例('testAssist'
)中不需要进行注入,我只能验证提供者是否有it
方法。请注意,第一个configure
调用是常规模块定义,而第二个angular.module
调用是模拟框架(module
)中的特殊构造。
我已将上述解决方案推送到GitHub上的fix1 branch。
答案 1 :(得分:-1)
您无法使用inject
获取提供者实例,而是使用module