角度测试模块和替代

时间:2019-03-21 16:41:16

标签: angular testing module karma-jasmine

我是角度测试的初学者,我的问题可能是“角度测试最佳实践”的一部分。

我正在寻找一种方法,在测试中包括最小的模块,并覆盖我需要嘲笑的某些部分。

比方说,我有一个需要路由器工作的按钮组件。它的模块是这样的:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MyButtonComponent } from './mybutton.component';
import { Router } from '@angular/router';
@NgModule({
  imports: [
    CommonModule,
  ],
  declarations: [
    MyButtonComponent,
  ],
  exports: [
    MyButtonComponent,
  ],
  providers: [
    Router,
  ]
})
export class MyButtonModule { }

现在我要像这样测试它:

import { TestBed, ComponentFixture } from '@angular/core/testing';
import { MyButtonModule } from './viewer-button.module';
import { RouterTestingModule } from '@angular/router/testing';

// Tests Begining
describe('ViewerButtonComponent', () => {
  let component: MyButtonComponent;
  let fixture: ComponentFixture<MyButtonComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        ViewerButtonModule,
        RouterTestingModule.withRoutes([]),
      ],
    })
    .compileComponents();

    fixture = TestBed.createComponent(MyButtonComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

  });

  it('#should create the component', () => {
    expect(component).toBeTruthy(' fail at creation');
  });
});

但是Router不会覆盖RouterTestingModule的导入。 (出现了Can't resolve all parameters for Router: (?, ?, ?, ?, ?, ?, ?, ?).错误)

对于这个示例,我知道一个更好的方法是只声明MyButtonComponent,然后导入RouterTestingModule,但是我在问是否有一种方法可以在没有NO_ERRORS_SCHEMA浅的情况下使用较大的组件。

例如:

 beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        // my childs component module
        MyChildComponentModule1,
        MyChildComponentModule2,
        ...
        MyChildComponentModuleX,

        //the modules that mock what needed (or use custom mock in the providers part)
        RouterTestingModule,
        HttpClientTestingModule,
        ....
        SomethingTestingModule
      ],
    })
    .compileComponents();

    fixture = TestBed.createComponent(MyButtonComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

  });

1 个答案:

答案 0 :(得分:0)

RouterTestingModule用于暂存路由和导航。

这里有几点:

1)您不应该在小部件模块中提供Router。相反,您应该在RouterModule.forRoot()上添加AppModule,以提供Router服务及其依赖项。

2)您不应创建混合的Angular模块,这意味着不要在单个Angular模块中提供声明。

3)Angular模块导入顺序很重要。使用此导入顺序,RouterTestingModule的提供者将覆盖Router中的ViewButtonModule提供者。

TestBed.configureTestingModule({
  imports: [
    ViewerButtonModule,
    RouterTestingModule.withRoutes([]),
  ],
});

4)您始终可以使用Angular测试模块覆盖提供程序。例如

TestBed.overrideProvider(Router, { useValue: routerStub });

TestBed.configureTestingModule({
  providers: [
    { provide: Router, useValue: routerStub },
  ],
});

如果您有兴趣学习更多内容,可以保留我的文章Testing and Faking Angular Dependencies作为那些难以记住的细节的参考。