javascript异步测试中模拟延迟响应的核心是让被测逻辑感知等待而非阻塞测试,常用promise+settimeout构造可控延迟,或用msw配置delay模拟真实网络,配合超时与重试逻辑验证。

在 JavaScript 异步代码测试中模拟延迟响应,核心目标是让被测逻辑“感知到等待”,从而验证 loading 状态、超时处理、重试策略或 UI 交互节奏是否正确——而不是真的卡住测试进程。
用 Promise + setTimeout 构造可控延迟
这是最轻量、最通用的方式,适用于任何基于 Promise 的请求逻辑(如 fetch 封装、axios 调用、自定义 API 函数)。
- 手动返回一个 resolve 前延时的 Promise:
const delayedSuccess = () => new Promise(res => setTimeout(() => res({ data: 'ok' }), 500)); - 在 mock 中使用它,例如:
vi.mock('./api', () => ({ fetchData: vi.fn().mockImplementation(delayedSuccess) })); - 配合 await waitFor 或 act(React Testing Library)可断言 loading 元素是否出现、是否在延迟后更新
用 msw 模拟带 delay 的真实网络行为
MSW(Mock Service Worker)适合需要贴近浏览器真实行为的场景,比如测试请求取消、加载骨架屏、或与 AbortController 协作的逻辑。
- 配置 delay(单位毫秒):
rest.get('/api/users', (req, res, ctx) => { return res(ctx.delay(800), ctx.status(200), ctx.json([{ id: 1 }])) }); - 支持动态 delay:可根据请求头、查询参数返回不同延迟,便于覆盖多种网络条件
- 注意:delay 是服务端响应延迟,不会影响请求发起时机,因此能准确测试“发送后等待”的全流程
验证超时与降级逻辑时的配合技巧
单纯加 delay 不够,还需主动触发超时路径。关键不是让测试等 10 秒,而是让被测代码在合理时间内走完“等待 → 判定超时 → 执行 fallback”流程。
- 在被测函数中,确保设置了明确的 timeout(如 fetch 的 signal 或 axios 的 timeout 配置)
- 用 msw 的 ctx.delay(Infinity) 或返回永不 resolve 的 Promise(new Promise(() => {})),再配合 jest 的 jest.setTimeout(2000) 让测试本身超时——这能反向验证你的超时逻辑是否生效
- 更推荐方式:mock 请求函数,第一次调用返回 pending Promise,第二次调用 resolve/fail,用于测试重试间隔是否按预期延迟
避免常见误区
延迟模拟不是越“像真实网络”越好,而是要服务于测试意图。
- 不用 jest.useFakeTimers() 控制网络层时间 —— 它对 fetch/axios 无效,只影响 setTimeout/setInterval
- 不依赖 while(Date.now() 类忙等待,会阻塞事件循环,导致测试假死
- 不把 delay 写死在测试用例里(如 sleep(500)),而应通过 mock 返回值注入,保持测试可预测性和并行执行能力
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











