Puppeteer仅首个请求响应正常,其余测试用例报404问题排查
问题原因
- 首个测试用例处理完目标请求后,调用了
page.setRequestInterception(false)直接关闭了全局请求拦截功能,后续测试用例即使重新开启拦截,也会因为状态未正确重置而失效。 page.off("request", requestHandler)虽移除了当前用例的拦截器,但如果测试用例间未做页面状态隔离,后续请求无法被新的拦截器捕获,导致请求未被拦截返回404。
修复方案
方案1:每个测试用例使用独立Page实例(推荐)
通过在beforeEach创建新页面、afterEach关闭页面,确保每个用例状态完全隔离:
describe("Login Providers Tests", function () { let page; beforeEach(async function () { page = await browser.newPage(); }); afterEach(async function () { await page.close(); }); it("Renders providers from core", async function () { await page.setRequestInterception(true); const requestHandler = (request) => { if (request.method() === "GET" && request.url() === LOGIN_METHODS_API) { request.respond({ status: 200, contentType: "application/json", body: JSON.stringify({ emailPassword: { enabled: true }, passwordless: { enabled: true }, thirdParty: { enabled: true, providers: [ { id: "apple", name: "Apple" }, { id: "github", name: "Github" }, ], }, }), }); } else { request.continue(); } }; page.on("request", requestHandler); await Promise.all([ page.goto(`${TEST_CLIENT_BASE_URL}${DEFAULT_WEBSITE_BASE_PATH}?authRecipe=thirdparty&multitenancy=enabled`), page.waitForNavigation({ waitUntil: "networkidle0" }), ]); const providers = await getProvidersLabels(page); assert.deepStrictEqual(providers, ["Continue with Apple", "Continue with Github"]); }); // 其他测试用例结构一致 });
方案2:单Page实例下重置拦截状态
若不想创建多页面,需在每个用例开始前重置拦截状态,且仅移除当前监听器、不关闭全局拦截:
it("Renders providers from core", async function () { // 重置拦截状态 await page.setRequestInterception(false); await page.removeAllListeners("request"); await page.setRequestInterception(true); const requestHandler = (request) => { if (request.method() === "GET" && request.url() === LOGIN_METHODS_API) { request.respond({ status: 200, contentType: "application/json", body: JSON.stringify({ emailPassword: { enabled: true }, passwordless: { enabled: true }, thirdParty: { enabled: true, providers: [ { id: "apple", name: "Apple" }, { id: "github", name: "Github" }, ], }, }), }); page.off("request", requestHandler); } else { request.continue(); } }; page.on("request", requestHandler); await Promise.all([ page.goto(`${TEST_CLIENT_BASE_URL}${DEFAULT_WEBSITE_BASE_PATH}?authRecipe=thirdparty&multitenancy=enabled`), page.waitForNavigation({ waitUntil: "networkidle0" }), ]); const providers = await getProvidersLabels(page); assert.deepStrictEqual(providers, ["Continue with Apple", "Continue with Github"]); });
关键注意事项
- 不要在单个用例中调用
page.setRequestInterception(false),否则会导致后续所有用例拦截功能失效。 - 每个测试用例开始前清除旧的请求监听器,避免多监听器冲突。
- 优先采用独立Page实例的方式,这是Playwright官方推荐的测试隔离最佳实践,能彻底避免状态污染问题。
内容的提问来源于stack exchange,提问作者howard wolowitz
相关产品推荐
相关产品推荐

