jest.setTimeoutで指定された5000msのタイムアウト時間内に非同期コールバックが呼び出されませんでした


238

私は操り人形師と冗談を使っていくつかのフロントエンドテストを実行しています。

私のテストは次のようになります:

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, async () => {
      await page.waitForSelector(PROFILE.TAB);
      await page.click(PROFILE.TAB);
    }, 30000);
});

テストを実行すると、すべてが期待どおりに動作することがあります。その他の場合、エラーが発生します。

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

      at node_modules/jest-jasmine2/build/queue_runner.js:68:21
      at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:633:19)

これは奇妙です。

  1. タイムアウトを30000に指定しました

  2. このエラーが発生するかどうかは非常にランダムに見える

なぜこれが起こっているのか誰でも推測できますか?


どのラインがタイムアウトしていますか?
ロイド

@Asool GitHubリポジトリを提供できますか?私たちがあなたにソリューションを提供することは、より簡単でより速くなります。:)
Shishir Anshuman

@Asool、私が投稿した回答に対するフィードバック
Tarun Lalwani

1
テストが実際に30000ms間失敗したが、jestからのエラーに単に渡した値が含まれていない可能性がありますか?つまり、0msタイムアウトを設定すると、jestエラーは変化しますか?
Nirit Levi

テストのデバッグ中にこのエラーが発生しました。ブレークポイントで停止するとこのエラーが発生しました
Neets

回答:


259

したがって、ここで指定するタイムアウトは、デフォルトのタイムアウトよりも短くする必要があります。

デフォルトのタイムアウトは5000で、フレームワークのデフォルトはのjasmine場合ですjest。以下を追加することで、テスト内のタイムアウトを指定できます

jest.setTimeout(30000);

しかし、これはテストに固有のものです。または、フレームワークの構成ファイルを設定できます。

https://facebook.github.io/jest/docs/en/configuration.html#setuptestframeworkscriptfile-string

// jest.config.js
module.exports = {
  // setupTestFrameworkScriptFile has been deprecated in
  // favor of setupFilesAfterEnv in jest 24
  setupFilesAfterEnv: ['./jest.setup.js']
}

// jest.setup.js
jest.setTimeout(30000)

このスレッドも参照してください

https://github.com/facebook/jest/issues/5055

https://github.com/facebook/jest/issues/652

PSのスペルミスsetupFilesAfterEnv(つまりsetupFileAfterEnv)も同じエラーをスローします。


2
Jestのドキュメントでは簡単に見つけられなかった質問に答えてくれてありがとう。
HartleySan

21
これが私を助けたので、setupTestFrameworkScriptFileがに置き換えられたことは注目に値するかもしれませんsetupFilesAfterEnv。そのため、それはsetupFilesAfterEnv: ["./jest.setup.js"]
Maxim Geerinck

1
jest.setTimeout(10000)エッジケースの単一のテストに追加できることもわかったので、構成全体を変更する必要はありませんでした:)
James

私は何かを見逃すべきですが、追加jest.setTimeout(30000);するjest.config.jsと「ReferenceError:jest is not defined」と表示されます。追加しようとしましたconst jest = require("jest");が、「TypeError:jest.setTimeout is not a function」と表示されます。
ジャンポール

おっと、私は速すぎて読みます。setupFilesAfterEnv引数はjest.config.jsjest.setTimeout(30000)オプションを配置した別のファイルを指しているものとします。これを設定できるのは良いことですが、少し複雑に思えます。
ジャンポール

64

async/awaitテストから非同期のときにを呼び出す必要があります。

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, async (done) => {
        await page.waitForSelector(PROFILE.TAB);
        await page.click(PROFILE.TAB);
        done();
    }, 30000);
});

24
なぜdone非同期関数が必要なのですか?単にPromiseまたはundefinedを返さないのですか?
チャーリーシュ

2
いいえ、これは正しくありません。あなたはあなたの約束を待っているか、単に戻ることができるので、あなたはdone()を呼び出す必要はありませんpage.click。done()は、少なくとも私の場合、主にコールバックでのテストに使用されます。
ジャスティン

2
みんなありがとう、私はdone必要のないコールバックを削除しました。
シュレディンガーのコード

26
これは元の質問と同じコードではありませんか?
ジョー

1
doneコールバックにパラメーター(この場合は名前が付けられています)があると、Jestはこのパラメーターが呼び出されるまで待機します。使用しなくても存在感はあります。
ボーン

54

この質問への答えは、ジェストが進化するにつれて変化しました。現在の回答(2019年3月):

  1. に3番目のパラメータを追加することで、個々のテストのタイムアウトを上書きできますit。すなわち。it('runs slow', () => {...}, 9999)

  2. を使用してデフォルトを変更できますjest.setTimeout。これをする:

 // config
   "setupFilesAfterEnv": [  // NOT setupFiles
     "./src/jest/defaultTimeout.js"
   ],

そして

// File: src/jest/defaultTimeout.js
/* global jest */
jest.setTimeout(1000)
  1. 他の人が指摘したように、これに直接関係しdoneないので、非同期/待機アプローチでは必要ありません。

5
これはよりモダンなバージョンです
-jonashdown

23

私は追加したいと思います(これはコメントには少し長いです)3000私のテストのタイムアウトでもまだ時々(ランダムに)失敗するでしょう

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

@Tarunのすばらしい回答のおかげで、私は多くのテストを修正する最も簡単な方法は次のとおりだと思います。

describe('puppeteer tests', () => {
  beforeEach(() => {
    jest.setTimeout(10000);
  });

  test('best jest test fest', async () => {
    // blah
  });
});

9
jest.setTimeout()内部beforeEachで呼び出す必要はありません。一度呼び出すだけで、すべてのテストで十分です。
Marcos Pereira

19

これは比較的新しいアップデートですが、はるかに簡単です。jest 24.9.0以降を使用している場合は、構成に追加testTimeoutするだけです。

// in jest.config.js
module.exports = {
  testTimeout: 30000
}

17

done();コールバックを呼び出すようにしてください。そうしないと、単にテストに合格するわけではありません。

beforeAll((done /* call it or remove it*/) => {
  done(); // calling it
});

done()コールバックを持つ他のすべての関数に適用されます。


1
よく言及されている、@ ZenVentzi。ありがとう:)!
ivanleoncz

11

jest 24.9+の場合は、コマンドラインからタイムアウトを設定することもできます。 --testTimeout

ここにそのドキュメントからの抜粋があります

--testTimeout=<number>
Default timeout of a test in milliseconds. Default value: 5000.

3

私は最近、別の理由でこの問題に遭遇しました:を使用して同期的にいくつかのテストを実行していてjest -i、タイムアウトするだけでした。理由が何であれ、jest --runInBand-iエイリアスであることを意図しているにもかかわらず)を使用して同じテストを実行してもタイムアウトしません。

多分これは誰かを助けるでしょう ¯\_(:/)_/¯


1

タイムアウトの問題は、ネットワークが遅い場合、またはを使用して多くのネットワーク呼び出しが行われた場合に発生しますawait。これらのシナリオは、デフォルトのタイムアウト、つまり5000ミリ秒を超えています。タイムアウトエラーを回避するには、タイムアウトをサポートするグローバルのタイムアウトを増やすだけです。グローバルとその署名のリストは、ここにあります
Jest 24.9の場合


1
// in jest.setup.js
jest.setTimeout(30000)

Jestが23以下の場合:

// in jest.config.js
module.exports = {
  setupTestFrameworkScriptFile: './jest.setup.js'
}

Jestが23より大きい場合:

// in jest.config.js
module.exports = {
  setupFilesAfterEnv: ['./jest.setup.js']
}


0

上記の使用方法の問題を誰かが修正しない場合は、非同期関数を矢印関数で囲んで修正しました。のように:

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, (() => {
      async () => {
        await page.waitForSelector(PROFILE.TAB)
        await page.click(PROFILE.TAB)
      }
    })(), 30000);
});

1
非同期関数の周りに矢印関数を置いても、テストが完了するのを待つようにテストに指示しないように思えるので、今はエラーが発生しないかもしれませんが、スレッドの外でテストが実行され、a)このテストを完了する前に、テストスイート全体が完了する可能性があります。このコードはテストされません。b)このテスト内の将来のエラーが、スイートの別のテスト中に表示され、テストが不安定になり、保守が困難になる可能性があります。
メアリーショー

0

私の場合、このエラーはランダムに発生し始め、タイムアウトを30000に設定しても消えません。ターミナルでプロセスを終了し、テストを再実行するだけで問題は解決しました。また、タイムアウトを削除しましたが、テストは再び成功しています。


-2

ノードでは...私が人々が例として行ったと思うことは以下を使用して、 fakeEventEmitter

import { EventEmitter } from 'events';
describe('your case', () => {
 let fakeEventEmitter: EventEmitter;
 beforeEach(async () => {
   fakeEventEmitter = new EventEmitter();
   (fakeEventEmitter as any).pid = 123;
 }),
 it('should do something you want to do', done => {
            anAsynchronouseFunction(testOptions, context).subscribe({
                complete: () => {
                    expect(something).toBeTruthy();
                    done();
                }
            });
            fakeEventEmitter.emit('exit', 0);
        });
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.