ChatGPT解决这个技术问题 Extra ChatGPT

消息“在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调”

我正在使用 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);
});

有时,当我运行测试时,一切都按预期工作。其他时候,我得到一个错误:

超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调。在 node_modules/jest-jasmine2/build/queue_runner.js:68:21
在 Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:633:19)

这很奇怪,因为:

我将超时时间指定为 30000 是否收到此错误似乎很随机

为什么会这样?

哪条线路超时?
@Asool 你能提供一个 GitHub 存储库吗?我们为您提供解决方案将更加轻松快捷。 :)
@Asool,对我发布的答案的任何反馈
是不是测试实际上在 30000 毫秒内失败了,但是开玩笑的错误根本不包括您通过的值?意思是,如果你把 0ms 超时,开玩笑的错误会改变吗?
我在调试测试时看到了这个错误。在断点处停止导致出现此错误

P
Peter Mortensen

您在此处指定的超时需要比默认超时短。

默认超时为 5000,如果是 jest,框架默认为 jasmine。您可以通过添加来指定测试内的超时

jest.setTimeout(30000);

但这将特定于测试。或者您可以为框架设置配置文件。

Configuring Jest

// 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)

另请参阅这些线程:

setTimeout per test #5055

Make jasmine.DEFAULT_TIMEOUT_INTERVAL configurable #652

PS:拼写错误的setupFilesAfterEnv(即setupFileAfterEnv)也会抛出同样的错误。


感谢您回答我无法通过 Jest 文档轻松找到的问题。
由于这对我有帮助,值得注意的是 setupTestFrameworkScriptFile 已替换为 setupFilesAfterEnv,因此它变为 setupFilesAfterEnv: ["./jest.setup.js"]
我还发现 jest.setTimeout(10000) 可以添加到边缘情况的单个测试中,因此整个配置不需要更改:)
我应该错过一些东西,但如果我在 jest.config.js 中添加 jest.setTimeout(30000);,我会得到“ReferenceError:jest is not defined”。我尝试添加 const jest = require("jest"); 但后来我得到“TypeError:jest.setTimeout 不是函数”。
就我而言,仅将 jest.setTimeOut(10000) 放入 describe 对我有帮助。将它放在测试函数体中,也没有将超时指定为测试参数 it.only(nm, fn, 10000) 起作用。
E
Edward

当它与测试异步时,它应该调用 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);
});

为什么我们应该在异步函数中包含 done?我们不是简单地返回 Promise 或 undefined 吗?
不,这是不正确的。您无需调用 done(),因为您正在等待您的承诺,或者您可以直接返回 page.click。 done() 至少在我的情况下主要用于回调测试。
谢谢大家,我已经删除了不需要的 done 回调。
这不是与现在原始问题中的代码相同吗?
回调中存在参数(在本例中名为 done)导致 Jest 等待直到调用此参数。即使不使用它,它的存在也很重要。
P
Peter Mortensen

随着 Jest 的发展,这个问题的答案也发生了变化。当前答案(2019 年 3 月):

您可以通过向其中添加第三个参数来覆盖任何单个测试的超时。即 it('runs slow', () => {...}, 9999) 您可以使用 jest.setTimeout 更改默认值。为此: // 配置 "setupFilesAfterEnv": [ // NOT setupFiles "./src/jest/defaultTimeout.js" ], 和 // 文件: src/jest/defaultTimeout.js /* 全局 jest */ jest.setTimeout (1000) 就像其他人指出的那样,并且与此没有直接关系,异步/等待方法不需要完成。


这是更现代的版本
让我们对此进行投票以将其推向梯子......这是最好的答案!
e
e-shfiyut

这是一个相对较新的更新,但它更直接。如果您使用的是 Jest 24.9.0 或更高版本,您只需将 testTimeout 添加到您的配置中:

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

要生效,请确保再次“jest --watch”(如果它已经在运行)。
我希望这是公认的答案,比必须将此配置放在单独的文件中要简单得多。
这就像一个魅力,也是 jest.setTimeout 因为它自己的行不起作用。
P
Peter Mortensen

我想补充一点(评论有点长)即使超时 3000 我的测试有时仍会(随机)失败

超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调。

感谢 Tarun's great answer,我认为修复大量测试的最短方法是:

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

  test('Best Jest test fest', async () => {
    // Blah
  });
});

您无需在 beforeEach 中调用 jest.setTimeout(),调用一次就足以完成所有测试。
P
Peter Mortensen

对于 Jest 24.9+,我们只需要在命令行中添加 --testTimeout :

--testTimeout= 10000 // Timeout of 10 seconds

默认超时值为 5000(5000 毫秒 - 5 秒)。这将适用于所有测试用例。

或者,如果您只想给特定函数超时,那么您可以在声明测试用例时使用此语法。

test(name, fn, timeout)

例子

test('example', async () => {

}, 10000); // Timeout of 10 seconds (default is 5000 ms)

数字前的空格和等号似乎都过分了。它真的正确吗?它真的会按预期工作吗? (不是反问。)
@PeterMortensen 你是对的,空间不是必需的,如 here 所示。它应该是 --testTimeout=10000
e
e-shfiyut

对于 Jest 24.9+,您还可以通过添加 --testTimeout 从命令行设置超时。

以下是 its documentation 的摘录:

--testTimeout= 测试的默认超时时间(以毫秒为单位)。默认值:5000。


P
Peter Mortensen

确保在回调中调用 done();,否则它根本无法通过测试。

beforeAll((done /* Call it or remove it */ ) => {
  done(); // Calling it
});

它适用于所有其他具有 done() 回调的函数。


P
Peter Mortensen

另一种解决方案:在 the Jest configuration file 中设置超时,例如:

{ // ... other stuff here
    "testTimeout": 90000
}

P
Peter Mortensen

您还可以根据愚蠢的拼写错误获得超时错误。例如,这个看似无害的错误:

describe('Something', () => {
  it('Should do something', () => {
    expect(1).toEqual(1)
  })

  it('Should do nothing', something_that_does_not_exist => {
    expect(1).toEqual(1)
  })
})

产生以下错误:

FAIL src/TestNothing.spec.js (5.427s)
  ● Something › Should do nothing

    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:678:19)

虽然发布的代码示例没有受到此影响,但它可能是其他地方失败的原因。另请注意,我没有在任何地方设置超时 - 无论是在此处还是在配置中。 5000 ms 只是默认设置。


错误是什么?您给回调一个参数 something_that_does_not_exist 的事实?
是的。在 JavaScript 中为函数提供额外未使用的参数通常是没有意义的,但却是良性的。这里很可能会产生上述令人困惑的错误。
P
Peter Mortensen

我最近出于不同的原因遇到了这个问题:我正在使用 jest -i 同步运行一些测试,它会超时。无论出于何种原因,使用 jest --runInBand 运行相同的测试(即使 -i 是一个别名)也不会超时。


P
Peter Mortensen
// 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']
}

这样做是行不通的,我收到一个关于“jest undefined”的错误(以及这个线程上的其他人)。我们不必在 jest 设置文件中导入 jest...
P
Peter Mortensen

当网络速度较慢或使用 await 进行许多网络调用时,会出现超时问题。这些场景超过了默认超时时间,即 5000 毫秒。为避免超时错误,只需增加支持超时的全局变量的超时时间。可以在 here 中找到全局变量列表及其签名。

开玩笑 24.9


P
Peter Mortensen

如果有人没有解决问题,请使用上述方法。我通过用箭头函数包围异步函数来修复我的问题。如:

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);
});

在我看来,将箭头函数放在 async 周围不会告诉测试等待测试完成,所以虽然您现在可能不会收到错误,但您将在其线程之外运行一个测试并且 a)整个测试套件可能会在此测试完成之前完成,而不是测试此代码,并且 b) 此测试中的未来错误可能会在套件中的不同测试期间出现,从而使您的测试不稳定且难以维护。
X
Xchai

事实证明,如果您的预期断言是错误的,它有时会吐出超出超时的错误消息。

我可以通过将 console.log() 语句放在我的 promise 回调中来解决这个问题,并看到 console.log() 语句在开玩笑的输出中运行。一旦我修复了我的期望断言,超时错误就消失了,测试工作正常了。

我花了太长时间才弄清楚这一点,并希望这对需要阅读本文的人有所帮助。


J
Jingguo Yao

test 接受 timeout 参数。请参阅https://jestjs.io/docs/api#testname-fn-timeout。这是一个示例:

async function wait(millis) {
  console.log(`sleeping for ${millis} milliseconds`);
  await new Promise(r => setTimeout(r, millis));
  console.log("woke up");
}
test('function', async () => {
  await wait(5000);
}, 70000);

J
Jingguo Yao

2022 年 3 月 14 日,Jest 27.5 文档指出了一个新流程:

https://jestjs.io/docs/api#beforeallfn-timeout

传递第二个参数以测试超时前的毫秒数。作品!

test('adds 1 + 2 to equal 3', () => {
    expect(3).toBe(3);
},30000);

P
Peter Mortensen

对于那些正在寻找有关 jest --runInBand 的解释的人,您可以转到文档。

在 CI 环境中运行 Puppeteer

GitHub - smooth-code/jest-puppeteer: Run your tests using Jest & Puppeteer


P
Peter Mortensen

就我而言,这个错误开始随机出现,即使设置了 30000 的超时时间也不会消失。只需在终端中结束进程并重新运行测试即可解决我的问题。我还删除了超时,测试仍然再次通过。


a
albanx

在这里放下我的 2 美分,我在 jest 单元测试的剂量(不是全部)上遇到了同样的问题,我注意到这一切都是在我为 MutuationObservers 添加到 jestSetup 这个 polyfill 之后开始的:

if (!global.MutationObserver) {
    global.MutationObserver = function MutationObserverFun(callback) {
        this.observe = function(){};
        this.disconnect = function(){};
        this.trigger = (mockedMutationsList) => {
            callback(mockedMutationsList, this);
        };
    };
}

一旦我删除它测试开始再次正常工作。希望对某人有所帮助。


S
SauerTrout

这可能对大多数访问此页面的人没有太大帮助,但是当我收到此错误时,它与 Jest 无关。我的一个方法调用是在本地运行时获得一个空对象和一个空异常。一旦我添加了一个空检查,失败的测试和有问题的控制台日志就消失了。

if(response !== null){
    this.searchSubj.next(resp);
 }
 else {
    return;
 }

R
Reck

对于大于 27 的 jest 版本,您可以在规范文件的顶部添加 useRealTimers

这是片段

import { shortProcess, longProcess } from '../../src/index';

jest.useRealTimers();

describe(`something`, function () {
    it('should finish fine', async function () {
        await shortProcess();
        expect(1).toBe(1);
    });

    it('should fail with a timeout', async function () {
        await longProcess();
        expect(1).toBe(1);
    });

    it('should finish fine again', async function () {
        jest.setTimeout(10 * 1000);
        await longProcess();
        expect(1).toBe(1);
    }, 10000);
});

在 jest 存储库中找到 github 问题 here


A
AN German

在你的测试中添加这个,不多解释

beforeEach(() => {
  jest.useFakeTimers()
  jest.setTimeout(100000)
})

afterEach(() => {
  jest.clearAllTimers()
})

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅