在jest.setTimeout指定的5000ms超时内未调用异步回调


237

我正在使用puppeteer和jest进行一些前端测试。

我的测试如下所示:

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. 我是否收到此错误似乎非常随机

有人能猜出为什么会这样吗?


哪条线超时?
lloyd

@Asool您可以提供GitHub存储库吗?为我们提供解决方案将更加轻松快捷。:)
Shishir Anshuman

@Asool,对我发布的答案有任何反馈
Tarun Lalwani

1
难道测试实际上在30000ms内失败了,但是开玩笑的错误根本不包括您传递的值?意思是,如果您将0ms超时,玩笑的错误会改变吗?
Nirit Levi

我在调试测试时看到此错误。在断点处停止导致出现此错误
Neets

Answers:


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文档找到的问题。
哈特利

21
由于这对我有帮助,因此可能值得注意的是,该位置setupTestFrameworkScriptFile已被替换为setupFilesAfterEnv,因此变成了setupFilesAfterEnv: ["./jest.setup.js"]
Maxim Geerinck,

我发现也jest.setTimeout(10000)可以将其添加到针对边缘情况的单个测试中,因此不需要更改整个配置:)
James

我应该错过一些东西,但是如果添加jest.setTimeout(30000);,则会出现jest.config.js“ ReferenceError:未定义笑话”的信息。我尝试添加,const jest = require("jest");但随后出现“ TypeError:jest.setTimeout不是函数”。
Jean Paul

糟糕,我读得太快了:setupFilesAfterEnvin中的参数jest.config.js将指向放置jest.setTimeout(30000)选项的另一个文件。我们可以配置它很好,但是对我来说似乎有点复杂。
Jean Paul

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还是未定义?
查理·施利瑟

2
不,这是不正确的。您不需要调用done(),因为您正在等待诺言,也可以返回page.click。至少在我的情况下,done()主要用于测试回调。
贾斯汀

2
谢谢大家,我删除了done不需要的回调。
薛定inger的代码

26
这与原始问题中的代码不同吗?

1
done回调中存在参数(在本例中为该参数命名)会导致Jest等待直到调用此参数。即使不使用它,它的存在也很重要。
沃恩

54

随着Jest的发展,这个问题的答案已经改变。当前答案(2019年3月):

  1. 您可以通过在中添加第三个参数来覆盖任何单个测试的超时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,这些情况超出了默认超时时间,即5000ms。为了避免超时错误,只需增加支持超时的全局变量的超时时间即可。全局列表及其签名可以在此处找到。
对于笑话24.9


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

如果开玩笑<= 23:

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

如果开玩笑> 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

在Node ...中,我看到人们作为示例在下面使用 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);
        });
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.