关键在于模拟网络状态而非等待函数执行完毕:用 mock 拦截请求验证延迟响应、abort 中断、指数退避重试及卸载清理,禁用同步轮询,所有判断须在异步回调中完成。

测试长轮询异步函数,关键不是等它“跑完”,而是验证它在不同网络状态下的行为是否可控、可中断、可重试。重点在于模拟响应延迟、中断信号、失败重试等真实场景,而不是让测试卡在真实请求里。
用 mock 请求 + 递归控制代替真实 API
不要在测试中调用真实后端接口。改用 cy.intercept()(Cypress)或 jest.mock('node-fetch')(Jest)拦截 fetch 请求,返回可控响应:
- 首次请求返回空数据或 pending 状态,触发下一轮
- 第二次请求返回目标值(如
{ status: 'CONFIRMED' }),验证轮询是否终止 - 故意返回 500 或超时,检查错误处理与退避逻辑是否生效
必须覆盖的中断路径
长轮询若不能被干净中断,极易导致内存泄漏或重复回调。测试需显式验证以下中断方式:
- 调用
abortController.abort()后,后续请求不再发起,且当前 pending 请求收到AbortError - 页面卸载前(
beforeunload)是否自动清理定时器或 abort 控制器 - 用户手动停止后,即使服务端还在响应,客户端也不再处理新数据
验证重试策略是否按预期执行
重试不是简单地“失败就再发一次”。测试要确认:
立即学习“Java免费学习笔记(深入)”;
- 连续失败时,延迟时间是否符合指数退避(如 100ms → 200ms → 400ms)
- 达到最大重试次数后,是否抛出最终错误,而非静默失败
- 重试判定函数
shouldRetry是 Promise 类型时,能否 await 权限检查或 token 刷新结果
避免同步轮询陷阱
切勿在测试中写 while (!condition) {} 或 await sleep(100) 等待状态——这会阻塞事件循环,导致 Cypress 超时或 Jest 崩溃。正确做法是:
- 用递归
cy.request().then(...)实现请求轮询(Cypress) - 用
waitFor+ 自定义异步条件(如async () => api.getState() === 'done')配合超时限制(Jest) - 所有状态判断必须发生在异步回调内,确保读取的是最新响应


















