You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest Puppeteer钩子超时问题:jest.setTimeout的正确使用位置

Jest Puppeteer测试超时及代码问题排查

问题描述

我是Jest Puppeteer新手,运行他人编写的测试套件时所有测试均失败,报错指向beforeEach钩子:

thrown: "Exceeded timeout of 5000 ms for a hook. Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

询问jest.setTimeout的正确放置方式,以及代码中是否存在其他配置错误或遗漏点。附上的测试代码如下:

const baseURL = "http://localhost:1234";
const puppeteer = require('puppeteer');

beforeEach(() => {
  // Reset mock function's states before each test.
  jest.clearAllMocks();
});


describe("chatbot", () => {
  beforeEach(async () => {
    const browser = await puppeteer.launch({headless: false, slowMo: 250,});
    const page = await browser.newPage();

  
    await page.goto(baseURL, { waitUntil: "load" });
    // set the fade-ins to 0 ms to prevent timeouts in tests
    await page.evaluate(() => { window.animationDelay = 0 })
    await page.click("#chat-circle");

    await browser.close()
  });



  it("should show contact info when the user enters 'contact'", async () => {
    // submit the form with a message, expect to see the response
    const message = "contact";
    await page.evaluate(() => {
      // get this same const in the page's context
      const message = "contact";
      $("#chat-input").val(message)
    });
    await page.click("#chat-submit");
    await expect(page).toMatch("We have 24 hour phone support. Our phone number is +01 312 555 8432. We look forward to hearing from you!");
  });

  it("should show credit card help message when the user enters 'credit card'", async () => {
    // submit the form with a message, expect to see the response
    const message = "credit card";
    await page.evaluate(() => {
      // get this same const in the page's context
      const message = "credit card";
      $("#chat-input").val(message)
    });
    await page.click("#chat-submit");
    await expect(page).toMatch("You can pay with any major credit card. Enter your card details and billing address at checkout.");
  });

  it("should show payment help message when the user enters 'payment'", async () => {
    // submit the form with a message, expect to see the response
    const message = "payment";
    await page.evaluate(() => {
      // get this same const in the page's context
      const message = "payment";
      $("#chat-input").val(message)
    });
    await page.click("#chat-submit");
    await expect(page).toMatch("We have three payment options: credit card, paypal, or apple pay. Choose your preferred method at checkout.");
  });

  it("should show help options when the users enters 'help'", async () => {
    // submit the form with a message, expect to see the response
    const message = "help";
    await page.evaluate(() => {
      // get this same const in the page's context
      const message = "help";
      $("#chat-input").val(message)
    });
    await page.click("#chat-submit");
    await expect(page).toMatch("Enter a keyword for help with a topic: contact, payment, credit card, destinations.");
  });
});

解决方案

一、解决beforeEach超时:正确放置jest.setTimeout

有三种可行方式,根据需求选择:

  1. 作用于整个describe块:放在describe内部最上方,对块内所有钩子和测试用例生效
describe("chatbot", () => {
  jest.setTimeout(15000); // 设为15秒,可根据实际加载速度调整

  beforeEach(async () => {
    // ... 钩子代码
  });

  // ... 测试用例
});
  1. 作用于单个beforeEach钩子:直接在钩子内部设置
beforeEach(async () => {
  jest.setTimeout(15000);
  // ... 钩子代码
});
  1. 全局配置:在项目根目录的jest.config.js中添加全局超时设置,对所有测试生效
module.exports = {
  testTimeout: 15000,
  // 其他Jest配置
};

二、代码中的其他致命错误修复

除了超时,原代码存在几个严重逻辑错误,是导致测试失败的核心原因:

  1. 提前关闭浏览器
    原beforeEach最后执行了await browser.close(),但测试用例还需要操作页面,这会直接导致所有测试因浏览器已关闭而失败。正确做法是将浏览器和page实例提升到describe作用域,在afterEach钩子中关闭浏览器:
describe("chatbot", () => {
  let browser;
  let page;

  beforeEach(async () => {
    jest.setTimeout(15000);
    browser = await puppeteer.launch({headless: false, slowMo: 250,});
    page = await browser.newPage();

    await page.goto(baseURL, { waitUntil: "load" });
    await page.evaluate(() => { window.animationDelay = 0 })
    await page.click("#chat-circle");
    // 移除此处的browser.close()
  });

  // 每个测试完成后关闭浏览器
  afterEach(async () => {
    await browser.close();
  });

  // ... 测试用例
});
  1. 测试用例中page变量未定义
    原代码的page是beforeEach内部的局部变量,测试用例无法访问,必须将其提升到describe作用域(如上代码所示),否则测试用例中的page.evaluate、page.click等操作都会报错。

  2. page.evaluate的变量传递优化
    原代码在page.evaluate内部重复定义message变量,可直接将外部变量传入,更简洁且避免冗余:

await page.evaluate((msg) => {
  $("#chat-input").val(msg);
}, message); // 将外部的message作为参数传入
  1. 断言前等待内容渲染
    await expect(page).toMatch(...)可能因页面内容未及时渲染而失败,建议配合page.waitForFunction等待目标文本出现后再断言:
await page.click("#chat-submit");
// 等待目标文本出现在页面中
await page.waitForFunction((text) => document.body.textContent.includes(text), {}, "We have 24 hour phone support...");
await expect(page).toMatch("We have 24 hour phone support. Our phone number is +01 312 555 8432. We look forward to hearing from you!");

内容的提问来源于stack exchange,提问作者Jessi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:51:18