できない.dev

Jest で「Exceeded timeout of 5000 ms for a test」が出てテストが完了できない

Jest の既定タイムアウトは 1 テスト 5 秒で、超えると失敗する。
本当に時間が必要ならタイムアウト値を延ばし、多くの場合は resolve されない Promise や done の呼び忘れといった非同期処理の問題を疑う。

公開:

要約

thrown: "Exceeded timeout of 5000 ms for a test." は、1 つのテストが Jest の既定タイムアウトである 5 秒以内に終わらなかったときに出る。

本当に時間のかかるテストならタイムアウト値を延ばせばよい。
ただし体感では、原因の多くは「終わらない非同期処理」で、タイムアウトを延ばしても解決しない。
まずテストが何を待ち続けているのかを確認する。

よくある原因

  1. 本当に遅い: 外部 API・実 DB アクセス・重い計算など、5 秒を超える処理をそのまま実行している。
  2. done の呼び忘れ: コールバック形式のテストで done を受け取ったのに、分岐によっては一度も呼ばれない。
  3. await 漏れ・未解決の Promise: resolve されない Promise を待っている、またはモックの設定漏れで応答が返らない。
  4. フェイクタイマー: jest.useFakeTimers() を有効にしたまま setTimeout 依存の処理を実時間で待っている。

解決策

1. テスト単位でタイムアウトを延ばす

it("重い統合テスト", async () => {
  const result = await runHeavyJob();
  expect(result.ok).toBe(true);
}, 10000);

第 3 引数にミリ秒を渡すと、そのテストだけタイムアウトが変わる。

2. 全体のタイムアウトを変更する

// jest.config.js
module.exports = {
  testTimeout: 10000,
};

ファイル単位なら jest.setTimeout(10000) をそのファイルの先頭やセットアップで呼ぶ。jest.setTimeout() は呼び出したテストファイルにだけ効く(jest オブジェクトの公式ドキュメント(新しいタブで開く))。

3. 終わらない非同期処理を直す

タイムアウトを延ばしても落ち続けるなら、待ち先が終わっていない。done 形式なら全分岐で done() が呼ばれるか、Promise 形式なら await の対象が本当に resolve されるかを確認する。
モックの戻り値を設定し忘れて、応答が永遠に返らないケースも多い。

4. フェイクタイマーを進める

jest.useFakeTimers();
// ...
jest.advanceTimersByTime(3000);

フェイクタイマー有効時は setTimeout が実時間では発火しない。
タイマーを進めるか、そのテストでは jest.useRealTimers() に戻す。

この記事は役立ちましたか?