【问题标题】:Message "Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout"消息“在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调”
【发布时间】:2018-09-11 05:41:37
【问题描述】:

我正在使用 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 毫秒超时内未调用异步回调。

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

这很奇怪,因为:

  1. 我将超时时间指定为 30000

  2. 我是否得到这个错误似乎是非常随机的

为什么会这样?

【问题讨论】:

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

标签: javascript automated-tests jestjs puppeteer


【解决方案1】:

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

默认超时为5000,框架默认为jasminejest。您可以通过添加来指定测试内部的超时时间

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

P.S.:拼写错误的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)
【解决方案2】:

当它与测试异步时,它应该调用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 等待直到调用此参数。即使不使用,它的存在也很重要。
【解决方案3】:

我想补充一点(评论有点长)即使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(),调用一次就足够了。
【解决方案4】:

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

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

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

【讨论】:

    【解决方案5】:

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

    1. 您可以通过向it 添加第三个参数来覆盖任何单个测试的超时。即it('runs slow', () =&gt; {...}, 9999)

    2. 您可以使用jest.setTimeout 更改默认值。为此:

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

      // File: src/jest/defaultTimeout.js
      /* Global jest */
      jest.setTimeout(1000)
      
    3. 正如其他人所指出的,与此没有直接关系,done 对于 async/await 方法不是必需的。

    【讨论】:

    • 这是更现代的版本
    • 让我们投票以将其推向阶梯......这是最好的答案!
    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

      对于那些正在寻找关于 jest --runInBand,你可以去看文档。

      在 CI 环境中运行 Puppeteer

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

      【讨论】:

        【解决方案8】:

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

        玩笑 24.9

        【讨论】:

          【解决方案9】:

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

          这是its documentation的摘录:

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

          【讨论】:

            【解决方案10】:
            // In jest.setup.js
            jest.setTimeout(30000)
            

            如果开玩笑

            // 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...
            【解决方案11】:

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

            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) 此测试中的未来错误可能会出现在套件中的不同测试期间,使您的测试不稳定且难以维护.
            【解决方案12】:

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

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

            【讨论】:

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

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

            【讨论】:

              【解决方案14】:

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

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

              【讨论】:

                【解决方案15】:

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

                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 毫秒只是默认设置。

                【讨论】:

                • 错误是什么?事实上你给回调一个参数something_that_does_not_exist?
                • 是的。在 JavaScript 中为函数提供额外未使用的参数通常是没有意义的,但却是良性的。这里很可能会产生上述令人困惑的错误。
                【解决方案16】:

                对于 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
                【解决方案17】:

                不幸的是,jest 不适用于 async/await。这就是我们传递done 回调的原因。不要在try/catch 中使用async/await,而是使用then/catch

                如果您希望测试成功运行,请在 then 中调用它,如果您希望测试失败,请在 catch 中调用 done。如果done 函数在 5000 毫秒内没有被调用,开玩笑会抛出错误。

                如果您将doneasync/await 一起使用,您将收到此错误。

                "Test functions cannot both take a 'done' callback and return something.
                 Either use a 'done' callback, or return a promise."
                

                解决办法如下:

                describe("Profile Tab Exists and Clickable: /settings/user", () => {
                    test(`Assert that you can click the profile tab`, (done) => {
                      // If you want this functionality passes, use inside then()
                      page.waitForSelector(PROFILE.TAB).then(()=>done())
                      // If you want this functionality fails, use inside catch()
                      page.click(PROFILE.TAB).catch(()=>done())
                    });
                });
                

                【讨论】:

                  【解决方案18】:

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

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

                  【讨论】:

                    【解决方案19】:

                    在这里放下我的 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);
                            };
                        };
                    }
                    

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

                    【讨论】:

                      【解决方案20】:

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

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

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

                      【讨论】:

                        【解决方案21】:

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

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

                        【讨论】:

                          猜你喜欢
                          • 2019-03-11
                          • 2018-09-18
                          • 2018-12-28
                          • 2019-04-23
                          • 2018-12-05
                          • 2020-05-13
                          • 2021-05-13
                          • 2020-01-15
                          相关资源
                          最近更新 更多