web-dev-qa-db-ja.com

Angular 4つのフィクスチャコンポーネントは、ジャスミンテスト中にDOMに保持されます

Jasmineを実際のブラウザで実行すると、TestBedフィクスチャコンポーネントはDOMで破棄されず、テスト終了後も持続することに気付きました。

enter image description here

テスト済みのコンポーネントは次のとおりです。

@Component({
  selector: 'test-app',
  template: `<div>Test</div>`,
})
class Test {}

テスト( plunk )。

  let component;
  let fixture;
  let element;

  beforeAll(() => {
    TestBed.resetTestEnvironment();

    TestBed.initTestEnvironment(
      BrowserDynamicTestingModule,
      platformBrowserDynamicTesting()
    );
  });

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

    fixture = TestBed.createComponent(Test);
    component = fixture.componentInstance;
    element = fixture.debugElement.query(By.css('div')).nativeElement;

    fixture.detectChanges();
  });

  afterEach(() => {
    fixture.destroy();
  });

  it('should compile Test', () => {
    expect(element).toBeTruthy();
  });

なぜTestコンポーネントインスタンスがDOMから削除されないのか、これをどのように修正する必要があるのですか?

フィクスチャコンポーネントがDOMに追加されるのはなぜですか? AngularJSの$rootElementのようにDOMからデタッチできますか?

26
Estus Flask

Angularは、テストの実行に関する詳細を取得するために自動的に削除されません。削除するには、単にafterEachを使用します。

beforeEach(() => {
  fixture = TestBed.createComponent(MyComponent);
  comp = fixture.componentInstance;
  debugElement = fixture.debugElement;
  element = debugElement.nativeElement;
});

 afterEach(() => {
  document.body.removeChild(element);
});
26

より簡潔なソリューション:

afterEach(() => {
  element.remove()
});

elementfixture.debugElement.nativeElement

4
Darwayne

次の問題をご覧ください。

1)まず、あなたが電話している

fixture.destroy();

afterEachであるため、itセクションの後に呼び出されます。つまりin itセクションフィクスチャはまだ破壊されていません

2)要素がまだDOMに存在することをどのコードで検出しますか?別の観点から:なぜその要素はジャスミン/ブラウザによって削除されるべきなのか(ジャスミン/ブラウザを作成する理由)次のユースケースを提案できます。

2.1)1つのコンポーネントが別のコンポーネントで使用されており、何らかの変更によって作成/破棄する必要があります。つまりngIfまたはngSwitchCase

<parent-component>
    <child-component *ngIf="someChangeInComponent1"></child-component>
</parent-component>

または

<parent-component [ngSwitch]="type">
    <child-component *ngSwitchCase="'something'"></child-component>
</parent-component>

2.2)ルーティングが変更されます(ただし、単体テストの対象ではありません)

3)現在のコードは、DOM要素への参照を1回だけ受け取ります。次のようなものでなければなりません:

beforeEach(() => {
    ...
    element = ...
});

it('...', () => {
    ...
    fixture.detectChanges();
    element = ... // try to get element again <--------------------- here
})

4)ngOnDestroy()のようなエラーを見つけようとしているが、implements OnDestroyが使用されていない場合、npm run lintの対象となります=単体テストより(tslint.jsonse-life-cycle-interfaceをご覧ください)。 npm run lintを実行すると、次のように表示されます。

Implement lifecycle hook interface OnDestroy for method ngOnDestroy in class ...

単体テストだけでなく、tslintにもエラーがないようにすることをお勧めします。

2
marbug