Angular2テスト-非同期関数呼び出し-いつ使用するか


86

Angular 2でテストするときに、TestBedで非同期関数を使用するのはいつですか?

いつ使うの?

 beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [MyModule],
            schemas: [NO_ERRORS_SCHEMA],
        });
    });

そして、いつこれを使用しますか?

beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [MyModule],
        schemas: [NO_ERRORS_SCHEMA],
    });
}));

誰かがこれについて私に教えてもらえますか?

回答:


95

asyncasyncすべてのタスクが完了するまで、次のテストを開始できません。何asyncんと、すべての非同期タスクが(例えばゾーンにコールバックを包んでsetTimeout)追跡されます。すべての非同期タスクが完了すると、async完了します。

Angularの外でJasmineを使用したことがある場合はdone、コールバックに渡されるのを見たことがあるかもしれません。

it('..', function(done) {
  someAsyncAction().then(() => {
    expect(something).toBe(something);
    done();
  });
});

ここでは、これはネイティブのJasmineであり、このテストはを呼び出すまで完了を遅らせる必要があることをJasmineに伝えますdone()。電話をかけずdone()、代わりにこれを行った場合:

it('..', function() {
  someAsyncAction().then(() => {
    expect(something).toBe(something);
  });
});

テストは同期タスクの実行が終了した後にPromiseが解決されるため、テストは予想よりも前に完了します。

Angular(Jasmine環境)では、doneを使用すると、Angularは実際に舞台裏で呼び出しますasync。ゾーン内のすべての非同期タスクを追跡し、それらがすべて終了doneすると、バックグラウンドで呼び出されます。

TestBed構成に関する特定のケースでは、一般的に、必要なときにこれを使用しcompileComponentsます。そうでなければそれを呼ばなければならない状況に遭遇することはめったにありません

beforeEach(async(() => {
   TestBed.configureTestingModule({
     declarations: [MyModule],
     schemas: [NO_ERRORS_SCHEMA],
   })
   .compileComponent().then(() => {
      fixture = TestBed.createComponent(TestComponent);
   });
}));

を使用するコンポーネントをテストするtemplateUrl場合(webpackを使用していない場合)、Angularはテンプレートを取得するためにXHRリクエストを行う必要があるため、コンポーネントのコンパイルは非同期になります。したがって、テストを続行する前に、問題が解決するまで待つ必要があります。


素晴らしい答え@peeskillet。念のために言っておきますが、インラインテンプレートがある場合は、async必要ありません。を使用templateUrlしている場合はです。ただし、asyncインクルードはインラインテンプレートコンポーネントを「破壊」しません。asyncすべてのテストにデフォルトで使用できると言っても差し支えないと思いますか?
ヴィンス2017年

2
@vincecampanale templateUrlは、beforeEachでの構成中にのみ重要です。その場合、を呼び出す必要がありますcompileComponents。それがasyncあなたが求めているものであるならば、それは各テストで使用することとは何の関係もありません。安全である限り(いつ呼び出すべきかcompileComponents)、いつcompileComponentsを呼び出すことになっているのかを
Paul Samsotha 2017年

2
@vincecampanaleテストのに呼び出す必要があるとは限りません。初期化を行った後で呼び出したい場合があります。あなたはそれを呼び出すことが実際に何をするのかを理解する必要があります。ただし、ほとんどの場合は問題ありません。しかし、私は個人的に、彼らがその決定を下すために彼ら自身にそれを引き受けたのが好きではありません。しかし、多くの人がそれを呼ぶのを忘れて問題にぶつかり、なぜ何かがうまくいかないのか疑問に思います。したがって、おそらく彼らが呼び出しを生成する方が良いでしょう。場所は議論の余地があるかもしれませんが、少なくとも彼らはそれを呼んでいます
Paul Samsotha 2017年

2
@vincecampanale一般に、ビューを(再)レンダリングする必要があるのは、それを呼び出す必要がある場合です。たとえば、[コンポーネントの作成]-> [ビューのレンダリング]。ただし、[コンポーネントの作成]-> [レンダリングに使用されるコンポーネントの値の変更]-> [ビューのレンダリング]のように、最初に何かを初期化する場合。それは私が意味することです多分あなたは最初に何かを初期化したいでしょう
Paul Samsotha 2017年

1
ああ、もう1つ。初めて呼び出すときngOnInitは、コンポーネント内で呼び出されるときです。テスト時にこれが問題になることがあります
Paul Samsotha 2017年

26

テストで非同期呼び出しを行うと、非同期呼び出しが完了する前に実際のテスト機能が完了します。呼び出しが完了したときに何らかの状態を確認する必要がある場合(通常はそうです)、非同期作業がまだ行われている間に、テストフレームワークはテストが完了したと報告します。

を使用しasync(...)て、テストフレームワークに、テストが完了したものとして扱う前に、リターンプロミスまたはオブザーバブルが完了するまで待機するように指示します。

it('should show quote after getQuote promise (async)', async(() => {
  fixture.detectChanges();

  fixture.whenStable().then(() => { // wait for async getQuote
    fixture.detectChanges();        // update view with quote
    expect(el.textContent).toBe(testQuote);
  });
}));

渡されたコードは、テスト関数自体が完了したthen(...)に実行されます。では、あなた、それが完了したように、テストを処理する前に、完全に約束し、観測を待つ必要があると、テストフレームワークに認識させます。async()

も参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.