typescript - Angular fakeAsync-test av oppløsning av løfte i ngOnInit()


Av en eller annen grunn vil ikke mine fakeAsync-tester løse enkle løfter. Jeg laget et minimalt eksempel som viser problemet (for det meste ng-generert standardkode).

Min komponent som testes inneholder en enkel direkte løfteoppløsning i sin ngOnInit-metode:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-simple-test',
  templateUrl: './simple-test.component.html',
  styleUrls: ['./simple-test.component.scss']
})
export class SimpleTestComponent implements OnInit {

  constructor() { }

  message: string;

  ngOnInit() {
    Promise.resolve('hello').then((content: string) => this.message = content);
  }

}

Jeg tester dette løftet med følgende test:

import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';

import { SimpleTestComponent } from './simple-test.component';

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ SimpleTestComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(SimpleTestComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should display "hello"', fakeAsync(() => {
    tick();
    expect(component.message).toBe('hello');
  }));
});

Men testen feiler, noe som betyr at løftet ikke er oppfylt på tidspunktet for expect, til tross for den tvungne oppfyllelsen av løftet via tick().

Det fungerer når man legger til et annet eksplisitt kall til component.ngOnInit() i begynnelsen av testen. Men dette resulterer i at ngOnInit() blir kalt to ganger. Så vidt jeg vet, bør fixture.detectChanges() i beforeEach() uansett ta seg av ngOnInit().

Hva går jeg glipp av? Hvorfor blir ikke løftet løst under tick()?

Svar #1

Fant problemet. ng g component genererer testen med fixture.detectChanges() i beforeEach(...)-funksjonen som er utenfor fakeAsync-sonen, så løftet kan ikke løses av tick().

Å flytte fixture.detectChanges() inn i fakeAsync-sonen fikser det for meg:

  beforeEach(() => {
    fixture = TestBed.createComponent(SimpleTestComponent);
    component = fixture.componentInstance;
  });

  it('should display "hello"', fakeAsync(() => {
    fixture.detectChanges();
    tick();
    expect(component.message).toBe('hello');
  }));

Svar #2

REDIGERT Du må kalle component.ngOnInit() først, deretter tick(), og så din expect-metode. Gjør dette i hver testmetode, det er det som fungerer for testene mine.

kodeutdrag

  beforeEach(() => {
    fixture = TestBed.createComponent(SimpleTestComponent);
    component = fixture.componentInstance;
  });

  it('should display "hello"', fakeAsync(() => {
    component.ngOnInit();
    tick();
    expect(component.message).toBe('hello');
  }));

Relaterte artikler