8

假设我有一个简单的模块AppModule,它有许多导入、声明和提供程序。现在我想为ListComponent这个模块的声明列表中的一个组件编写一个测试。ListComponent它本身使用了很多(但不是每个)导入的AppModule. 我这样做:

import { TestBed } from '@angular/core/testing';
// +same copy-pasted list of imports from `AppModule`

beforeEach(done => {
    TestBed.configureTestingModule({
        imports: [
            // +same copy-pasted list of imports from `AppModule`
        ],
        declarations: [
            // +same copy-pasted list of declarations from `AppModule`
        ],
        providers: [
            {
                provide: Http,
                useClass: HttpMock,
            },
            {
                provide: Router,
                useClass: RouterMock,
            }
            // +same copy-pasted list of providers from `AppModule`
        ]
    });

它有效,但肯定是一种不正确的方法。我不想复制粘贴这么多。也许我可以以某种方便的方式重用 AppModule?伪代码如下:

let appModule = new AppModule();

beforeEach(done => {
    TestBed.configureTestingModule({
        imports: appModule.imports,
        declarations: appModule.declarations,
        providers: [...appModule.providers,
            {
                provide: Http,
                useClass: HttpMock,
            },
            {
                provide: Router,
                useClass: RouterMock,
            }
        ]
    });

但我只是不知道/找不到这种方法的语法:(

4

2 回答 2

14

您可以创建可重用的 const,其中包含您想要的模块中的常用导入和提供程序。

例如,在 app.providers.ts 文件中,您可以让您的提供者像这样:

import service1 from '.path/service/service1';
import service2 from '.path/service/service2';

export const providers = [service1, service2 ];

并为您在 app.imports.ts 中的导入

import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { Module1} from ''.path/service/module1';

export const imports= [
    BrowserModule,
    AppRoutingModule,
    Module1
],

在您的 app.module.ts 和您想要使用相同导入和提供程序的任何其他模块上,您可以执行以下操作:

import { providers } from './app.providers';
import { imports } from './app.imports';
@NgModule({
    declarations: [AppComponent],
    imports: imports,
    providers: providers,
    bootstrap: [AppComponent]
})

您还可以使用扩展运算符将您的唯一导入添加到特定模块上的这些共享导入中。

于 2018-02-14T15:33:40.233 回答
1

您可以通过创建全局 TestBed 来避免提供一长串嵌套服务和依赖项。

虽然为提供程序和导入创建常量数组是解决此问题的一种方法,但我想将其带到下一步并在全局级别上配置 TestBed 以避免导入重复的模块。

为了配置全局测试床,我创建了一个通用测试模块,它具有配置测试床的实用方法。然后可以在所有规范文件中重复使用此方法。

public static setUpTestBed = (TestingComponent: any) => {
    beforeEach(() => {
      TestBed.configureTestingModule({
        imports: [
          ReactiveFormsModule,
          ...
        ],
        providers: [
          ...
        ],
        declarations: [TestingComponent],
        schemas: [CUSTOM_ELEMENTS_SCHEMA]
      });
    });
  }

CommonTestingModule:包含用于创建测试平台的实用方法。
LoginComponent: login.component.spec.ts -> 实用方法的引用

CommonTestingModule.setUpTestBed(LoginComponent);

下面给出完整的组件以供参考:

通用测试模块:

import { ChangeDetectionStrategy, CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { DatePipe } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { UtilityService } from '../services/utility.service';
import { TestBed } from '@angular/core/testing';

@NgModule({
  declarations: []
})
export class CommonTestingModule {

  public static setUpTestBed = (TestingComponent: any) => {
    beforeEach(() => {
      TestBed.configureTestingModule({
        imports: [
          ReactiveFormsModule,
          FormsModule,
          HttpClientTestingModule,
          RouterTestingModule,
          ... //other imports
        ],
        providers: [
          DatePipe,
          UtilityService,
          ... //other imports
        ],
        declarations: [TestingComponent],
        schemas: [CUSTOM_ELEMENTS_SCHEMA]
      });
    });
  }
}

然后在所有组件规范文件中,您现在可以引用实用方法CommonTestingModule.setUpTestBed(),它接受调用组件名称作为输入参数。

login.component.spec.ts

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
import { CommonTestingModule } from 'src/app/testing/common-testing.module';

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;

  CommonTestingModule.setUpTestBed(LoginComponent);

  beforeEach(() => {
    // create component and test fixture
    fixture = TestBed.createComponent(LoginComponent);
    // get test component from the fixture
    component = fixture.componentInstance;
    component.ngOnInit();
  });

  it('Component instantiated successfully', () => {
    expect(component).toBeTruthy();
  });

});

而已。您现在可以在所有规范文件中重用该实用程序方法。如果更适合您,您还可以创建一个 beforeAll 实用程序方法。

于 2020-11-14T15:57:50.793 回答