Angular2 单元测试导致竞争条件

Angular2 unit tests causing a race condition

我正在测试输入字段是否正确更新组件的 UI 字段。我遇到了竞争条件,其中一项测试的结果与另一项测试的预期结果进行了比较。

我的单元测试代码:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { EntityEditorComponent, EntityEditorModule } from '.';
import { Entity, EntityType } from '..';

describe('EntityEditorComponent template', () => {
  let target: EntityEditorComponent;
  let fixture: ComponentFixture<EntityEditorComponent>;
  let nameElement: HTMLInputElement;
  let typeElement: HTMLSelectElement;

  beforeEach(() => {
    TestBed.configureTestingModule({ imports: [ EntityEditorModule ] }).compileComponents();

    fixture = TestBed.createComponent(EntityEditorComponent);
    target = fixture.componentInstance;
    nameElement = fixture.debugElement.query(By.css('#name')).nativeElement as HTMLInputElement;
    typeElement = fixture.debugElement.query(By.css('#type')).nativeElement as HTMLSelectElement;
  });

  [
    { expectation: 'null', name: null       , expected: null        },
    { expectation: 'set' , name: 'Unit Test', expected: 'Unit Test' },
  ].forEach((test, i, tests) => {
    it('#name displays Entity.name when ' + test.expectation, () => {
      target.entity.name = test.name;

      fixture.detectChanges();
      fixture.whenStable().then(() => {
        let actual = nameElement.textContent;
        expect(actual).toEqual(test.expected);
      });
    });
  });

  [
    { expectation: 'null', type: null              , expected: null      },
    { expectation: 'set' , type: EntityType.Company, expected: 'Company' },
  ].forEach((test, i, tests) => {
    it('#type displays Entity.type when ' + test.expectation, () => {
      target.entity.type = test.type;

      fixture.detectChanges();
      fixture.whenStable().then(() => {
        let actual = typeElement.value;
        expect(actual).toEqual(test.expected);
      });
    });
  });
});

我看到的错误总结如下:

FAILED TESTS:
  EntityEditorComponent template
    × #type displays Entity.type when null
    Expected '' to equal null.

    × #type displays Entity.type when set
    Expected '' to equal 'Unit Test'.

#type 显示 Entity.type 测试如何看到 Unit Test 预期值?我能看到的唯一方法是它来自 #name 显示 Entity.name 测试。

显然我做错了什么。如何在不引起竞争条件的情况下测试检测到的更改?

没有 plunker 或代码片段,调查起来有点困难,但是您确实进行了具有异步期望的测试 运行。这保证您将回调传递给 it() 函数(按照惯例,这通常称为 done)。

试试以下方法:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { EntityEditorComponent, EntityEditorModule } from '.';
import { Entity, EntityType } from '..';

describe('EntityEditorComponent template', () => {
  let target: EntityEditorComponent;
  let fixture: ComponentFixture<EntityEditorComponent>;
  let nameElement: HTMLInputElement;
  let typeElement: HTMLSelectElement;

  beforeEach(() => {
    TestBed.configureTestingModule({ imports: [ EntityEditorModule ] }).compileComponents();

    fixture = TestBed.createComponent(EntityEditorComponent);
    target = fixture.componentInstance;
    nameElement = fixture.debugElement.query(By.css('#name')).nativeElement as HTMLInputElement;
    typeElement = fixture.debugElement.query(By.css('#type')).nativeElement as HTMLSelectElement;
  });

  [
    { expectation: 'null', name: null       , expected: null        },
    { expectation: 'set' , name: 'Unit Test', expected: 'Unit Test' },
  ].forEach((test, i, tests) => {
    it('#name displays Entity.name when ' + test.expectation, done => {
      target.entity.name = test.name;

      fixture.detectChanges();
      fixture.whenStable().then(() => {
        let actual = nameElement.textContent;
        expect(actual).toEqual(test.expected);
        done();
      });
    });
  });

  [
    { expectation: 'null', type: null              , expected: null      },
    { expectation: 'set' , type: EntityType.Company, expected: 'Company' },
  ].forEach((test, i, tests) => {
    it('#type displays Entity.type when ' + test.expectation, done => {
      target.entity.type = test.type;

      fixture.detectChanges();
      fixture.whenStable().then(() => {
        let actual = typeElement.value;
        expect(actual).toEqual(test.expected);
        done();
      });
    });
  });
});