单元测试:"InterceptableStoreFactory" 没有提供程序,即使添加到 "providers"
Unit Testing : No provider for "InterceptableStoreFactory" even if added to "providers"
我正在我的 Angular 应用程序中进行单元测试,我正在使用 TestBed 方法,
我正在测试组件,所以每个规范文件看起来像这样
import...
describe('AppComponent', () => {
// Importing dependecies
beforeEach(async(() => {
TestBed.configureTestingModule({
imports : [RouterTestingModule , HttpModule , FormsModule ],
declarations: [AppComponent
],
providers: [AUTH_PROVIDERS ,UserService, SharedclientService, RouteNavigator, JwtHelper, ReloadTokenService, ShopService
, EnvVarsService, ProfileService, LocalStorageService, ApiVersionInterceptor, ApiTrackingInterceptor, MonitoringService ,
{ provide: 'LOCAL_STORAGE_SERVICE_CONFIG', useValue: userConfig } , TokenUtilService , HttpInterceptorService ,
{ provide: InterceptableStoreFactory, useClass: InterceptableStoreFactoryMock },ReloadTokenEventService , InterceptableStoreFactory
]
}).compileComponents();
}));
// detecting changes every times
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// Test case 0 (compilation of the component)
it('AppComponent is well defined', () => {
expect(component).toBeDefined();
});
// Test case 1
it('test', () => {
expect("1").toBe("1");
});
});
如果依赖项导入不正确,这种测试方法会导致整个测试套件失败。
例如:在这个测试套件中,它抛出这个错误:
No provider for InterceptableStoreFactory!
It seems to be strange , as i'm importing this service in my providers (last one)
这导致几乎所有测试用例的失败,因为夹具导入的验证是“beforeEach”测试用例
正在寻找更好的想法:
- "no provider for service"的问题(已添加到提供者中)
和
- unit testBed 更好的测试方法
您提供了两次 InterceptableStoreFactory。一次是模拟替换,一次是原始。尝试删除其中之一。
它可能会帮助您为所有服务创建一个模块并将其放在 'core' 文件夹中。 (参见 Angular Style Guide)
这样可以更轻松地在测试和 development/production 中提供所有正确的服务,而无需重复那么多。
1.没有服务提供商
删除提供程序数组中的尾随 InterceptableStoreFactory
。因为你已经在同一行早些时候注入了模拟服务 InterceptableStoreFactory
。
如果这不能解决问题,请提供您的模拟片段 class InterceptableStoreFactoryMock
和 InterceptableStoreFactory
.
2。更好的测试策略
为了更好的测试策略,我建议一些事情来简化测试:
- 在 Angular 风格指南中建议 here:将所有全球服务合二为一
CoreModule
。然后您可以很容易地知道所有的服务都被导入并轻松地导入它们进行测试。如果您想以相同的方式为许多组件模拟其中的许多服务,我还建议您创建一个明确的 CoreTestingModule
。因此为所有测试保留re-usability。
- 在 Angular 样式指南中建议 here:一个
SharedModule
,您可以在其中导出组件、指令和管道,您 re-use 在整个应用程序中经常使用。
- 考虑使用非常小的模块。在 2017 年下半年或 2018 年初的一个会议的 FAQ 中,Rob Wormald 提到 Google Angular 项目中的每个模块平均只有 1.6 个组件。这意味着组件的每个测试都不太可能包含它实际上不需要的服务和其他导入。因此,如果您更改由很多组件使用的大模块,则还需要更少的测试重构。使用较小的模块,您的
TestBed
也会快得多,因为它在每个测试用例后 re-initialize 和 TestBed
的速度要快得多。
- 考虑将大部分逻辑移至服务和管道,并将测试重点主要转移到它们。由于测试服务和管道可以使用常规测试基础设施,因此可以跳过创建模块的复杂性,因为服务和管道可以像常规 classes 和函数一样对待。作为 side-note,我会提到这或多或少是通过迁移到 NGRX architecture 自动完成的。
- This issue 正在跟踪
TestBed
的更大性能改进。现在的问题是您必须 re-create 并在每个测试用例之间拆除模块。使其比仅测试服务、管道和其他纯函数和 classes 慢很多。正如前面提到的,这可以通过使用更小的模块来补救。该问题还显示了一些使用 Jest 或变通方法的技巧,这样模块就不需要为每个测试用例 re-created,而是 re-usable。然而,后者更改了私有 API,因此很容易让您的应用程序在 Angular 的补丁版本之间中断,这不是一个好地方。
我正在我的 Angular 应用程序中进行单元测试,我正在使用 TestBed 方法,
我正在测试组件,所以每个规范文件看起来像这样
import...
describe('AppComponent', () => {
// Importing dependecies
beforeEach(async(() => {
TestBed.configureTestingModule({
imports : [RouterTestingModule , HttpModule , FormsModule ],
declarations: [AppComponent
],
providers: [AUTH_PROVIDERS ,UserService, SharedclientService, RouteNavigator, JwtHelper, ReloadTokenService, ShopService
, EnvVarsService, ProfileService, LocalStorageService, ApiVersionInterceptor, ApiTrackingInterceptor, MonitoringService ,
{ provide: 'LOCAL_STORAGE_SERVICE_CONFIG', useValue: userConfig } , TokenUtilService , HttpInterceptorService ,
{ provide: InterceptableStoreFactory, useClass: InterceptableStoreFactoryMock },ReloadTokenEventService , InterceptableStoreFactory
]
}).compileComponents();
}));
// detecting changes every times
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// Test case 0 (compilation of the component)
it('AppComponent is well defined', () => {
expect(component).toBeDefined();
});
// Test case 1
it('test', () => {
expect("1").toBe("1");
});
});
如果依赖项导入不正确,这种测试方法会导致整个测试套件失败。
例如:在这个测试套件中,它抛出这个错误:
No provider for InterceptableStoreFactory! It seems to be strange , as i'm importing this service in my providers (last one)
这导致几乎所有测试用例的失败,因为夹具导入的验证是“beforeEach”测试用例
正在寻找更好的想法:
- "no provider for service"的问题(已添加到提供者中)
和
- unit testBed 更好的测试方法
您提供了两次 InterceptableStoreFactory。一次是模拟替换,一次是原始。尝试删除其中之一。
它可能会帮助您为所有服务创建一个模块并将其放在 'core' 文件夹中。 (参见 Angular Style Guide)
这样可以更轻松地在测试和 development/production 中提供所有正确的服务,而无需重复那么多。
1.没有服务提供商
删除提供程序数组中的尾随 InterceptableStoreFactory
。因为你已经在同一行早些时候注入了模拟服务 InterceptableStoreFactory
。
如果这不能解决问题,请提供您的模拟片段 class InterceptableStoreFactoryMock
和 InterceptableStoreFactory
.
2。更好的测试策略
为了更好的测试策略,我建议一些事情来简化测试:
- 在 Angular 风格指南中建议 here:将所有全球服务合二为一
CoreModule
。然后您可以很容易地知道所有的服务都被导入并轻松地导入它们进行测试。如果您想以相同的方式为许多组件模拟其中的许多服务,我还建议您创建一个明确的CoreTestingModule
。因此为所有测试保留re-usability。 - 在 Angular 样式指南中建议 here:一个
SharedModule
,您可以在其中导出组件、指令和管道,您 re-use 在整个应用程序中经常使用。 - 考虑使用非常小的模块。在 2017 年下半年或 2018 年初的一个会议的 FAQ 中,Rob Wormald 提到 Google Angular 项目中的每个模块平均只有 1.6 个组件。这意味着组件的每个测试都不太可能包含它实际上不需要的服务和其他导入。因此,如果您更改由很多组件使用的大模块,则还需要更少的测试重构。使用较小的模块,您的
TestBed
也会快得多,因为它在每个测试用例后 re-initialize 和TestBed
的速度要快得多。 - 考虑将大部分逻辑移至服务和管道,并将测试重点主要转移到它们。由于测试服务和管道可以使用常规测试基础设施,因此可以跳过创建模块的复杂性,因为服务和管道可以像常规 classes 和函数一样对待。作为 side-note,我会提到这或多或少是通过迁移到 NGRX architecture 自动完成的。
- This issue 正在跟踪
TestBed
的更大性能改进。现在的问题是您必须 re-create 并在每个测试用例之间拆除模块。使其比仅测试服务、管道和其他纯函数和 classes 慢很多。正如前面提到的,这可以通过使用更小的模块来补救。该问题还显示了一些使用 Jest 或变通方法的技巧,这样模块就不需要为每个测试用例 re-created,而是 re-usable。然而,后者更改了私有 API,因此很容易让您的应用程序在 Angular 的补丁版本之间中断,这不是一个好地方。