6

我正在我的 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");
    });
});

如果依赖项导入不好,这种测试方法会导致整个测试套件失败。

例如:在这个测试套件中,它会抛出这个错误:

没有InterceptableStoreFactory的提供者!这似乎很奇怪,因为我正在我的提供商中导入此服务(最后一个)

这导致几乎所有测试用例的失败,因为夹具导入的验证是“ beforeEach ”测试用例

我正在寻找更好的想法:

  1. “没有服务提供者”的问题(已添加到提供者中)

并且对于

  1. 单元测试床更好的测试方式
4

2 回答 2

3

您提供两次 InterceptableStoreFactory 。一次是模拟替换,一次是原始的。尝试删除其中之一。

它可以帮助您为所有服务创建一个模块并将其放在“核心”文件夹中。(见角度风格指南

这使得在测试和开发/生产中提供所有正确的服务变得更加容易,而无需过多地重复自己。

于 2018-03-23T09:56:20.983 回答
2

1.没有服务提供者

删除InterceptableStoreFactoryproviders 数组中的尾随。因为您已经InterceptableStoreFactory在同一行早些时候注入了模拟服务。

如果这不能解决它,请提供您的模拟类的片段InterceptableStoreFactoryMockInterceptableStoreFactory.

2. 更好的测试策略

为了获得更好的测试策略,我会建议一些使测试更容易的事情:

  1. 在 Angular Styleguide中建议:将所有全局服务收集到一个CoreModule. 然后,您可以轻松知道所有服务都已导入并轻松导入它们以进行测试。CoreTestingModule如果您想以相同的方式为许多组件模拟许多这些服务,我还建议您创建一个显式的。从而保留所有测试的可重用性。
  2. 在 Angular Styleguide 中建议:可以SharedModule在其中导出在应用程序中重复使用的组件、指令和管道。
  3. 考虑使用非常小的模块。在 2017 年下半年或 2018 年初的一次会议的 FAQ 中,Rob Wormald 提到 Google Angular 项目中的每个模块平均只有 1.6 个组件。这意味着组件的每个测试都不太可能包含它实际上不需要的服务和其他导入。因此,如果您更改由很多组件使用的大模块,也需要更少的测试重构。使用较小的模块,您的速度也会快得多,因为在每个测试用例之后TestBed重新初始化的速度要快得多。TestBed
  4. 考虑将大部分逻辑转移到服务和管道上,并主要将测试重点转移到它们身上。由于测试服务和管道可以使用常规测试基础设施,因此可以跳过创建模块的复杂性,因为服务和管道可以像常规类和函数一样对待。作为旁注,我会提到这或多或少是通过迁移到NGRX 架构自动完成的。
  5. 此问题正在跟踪对TestBed. 现在的问题是您必须在每个测试用例之间重新创建和拆除模块。比仅仅测试服务、管道和其他纯函数和类要慢得多。正如前面提到的,这可以通过使用更小的模块来解决。该问题还显示了一些使用 Jest 的技巧或变通方法,因此不需要为每个测试用例重新创建模块,而是可以重复使用。然而,后者更改了私有 API,因此很容易在 Angular 的补丁版本之间破坏您的应用程序,这不是一个好地方。
于 2018-03-29T16:28:17.080 回答