测试异步操作

有时候,我们需要测试依赖于在特定时间发生的异步操作的组件。 Angular提供了一个称为fakeAsync的函数,它将我们的测试包裹在一个区域中,并让我们访问tick函数,这将允许我们精确地模拟时间的流逝。

让我们回到QuoteComponent组件的例子,并使用fakeAsync重写单元测试:

import { Component } from '@angular/core';
import { QuoteService } from './quote.service';
@Component({
  selector: 'my-quote',
  template: '<h3>Random Quote</h3> <div>{{quote}}</div>'
})
export class QuoteComponent {
  quote: string;
  constructor(private quoteService: QuoteService){};
  getQuote() {
    this.quoteService.getQuote().then((quote) => {
      this.quote = quote;
    });
  };
}
import { QuoteService } from './quote.service';
import { QuoteComponent } from './quote.component';
import { provide } from '@angular/core';
import {
  async,
  TestBed,
  fakeAsync,
  tick,
} from '@angular/core/testing';
class MockQuoteService {
  public quote: string = 'Test quote';
  getQuote() {
    return Promise.resolve(this.quote);
  }
}
describe('Testing Quote Component', () => {
  let fixture;
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [
        QuoteComponent
      ],
      providers: [
        { provide: QuoteService, useClass: MockQuoteService }
      ]
    });
    fixture = TestBed.createComponent(QuoteComponent);
    fixture.detectChanges();
  });
  it('Should get quote', fakeAsync(() => {
    fixture.componentInstance.getQuote();
    tick();
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('div').innerText).toEqual('Test quote');
  }));
});

View Example

这里我们有一个QuoteComponent,它有一个getQuote触发异步更新。 我们将整个测试包装在fakeAsync中,这将允许我们通过调用tick()来使用同步函数调用来测试我们的组件(getQuote())的异步行为。 然后我们可以运行detectChanges并查询DOM的预期结果。

重构难以测试的代码

当你开始编写单元测试时,你可能会发现很多代码很难测试。 最好的策略通常是重构代码,使其易于测试。 例如,考虑将组件代码重构到服务中,并专注于服务测试,反之亦然。

下一节:当在Angular 2中测试服务时,我们采用了许多用于测试组件的相同技术和策略。 服务,类似组件,是具有我们想要验证的方法和属性的类。 数据是测试服务的主要重点 - 我们是否正确地获取,存储和传播数据。