🕳️

jestの非同期の落とし穴

2023/08/23に公開

非同期の落とし穴

以下のテストは 1が2でないことは明らかですが、テストはパスします。これは非同期呼び出しの落とし穴です。2行目は setTimeoutを呼び出しリターンし、テストは3行目が実行される前に終了します。it関数内で expect がなくてもテストは成功します。

it('should fail this test', () => {
  setTimeout(() => {
    expect(1).toBe(2) // should fail this line!
  });
  // PASS!
});

解決策 ①

解決策 ①は expect.assertionsを使います。expect.assertions(number)は、テスト中に一定数のアサーションが実行されたことを確認します。

it('should fail this test', () => {
  expect.assertions(1);
  setTimeout(() => {
    expect(1).toBe(2) // should fail this line!
  });
  // FAIL! Expected one assertion to be called but received zero assertion calls.
});

解決策 ②

jest の done コールバックをテストケースに渡し、setTimeout が終了するまで待つことで、このテストは期待通り失敗します。

it("should fail this test", (done) => {
  setTimeout(() => {
    expect(1).toBe(2); // FAIL!
    done(); 
  });
});

解決策 ③

解決策 ③ は 解決策 ② とやっていることは同じです。Promise オブジェクトを作成し、テストケースの中で resolve されるまで待つことで解決できます。

it("should fail this test", async () => {
  await new Promise<void>((resolve) => {
    setTimeout(() => {
      expect(1).toBe(2); // FAIL!
      resolve();
    });
  });
});

Discussion