模拟网络超时应mock延迟拒绝的promise,如axios用vi.fn().mockimplementation(() => new promise((_, reject) => settimeout(() => reject(new error('timeout')), 4000))),fetch可结合abortcontroller.abort()返回aborterror,确保延迟略超代码超时阈值,并验证降级、重试、ui反馈等完整业务响应。

模拟网络超时异常,核心不是让测试“等真超时”,而是让被测代码接收到一个符合生产环境行为的 TimeoutError 或等效拒绝信号,并验证其降级、重试或 UI 反馈逻辑是否正确触发。
用 mock 返回延迟拒绝的 Promise
这是最常用、最可控的方式。不依赖真实网络,也不需要 fake timers 干预 fetch/axios 底层。
- 对 axios:mock
get方法,先 delay 再 reject,例如:vi.fn().mockImplementation(() => new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 5000))) - 对 fetch:返回一个 5 秒后 reject 的 Promise,并确保错误类型接近真实(如
TypeError或自定义AbortError) - 关键点:延迟时间应略大于你代码中设置的超时阈值(比如代码设了 3s 超时,mock 延迟设 4s),才能真正触发超时分支
配合 AbortController 主动中断请求
某些业务逻辑会专门捕获 AbortError 来区分“用户取消”和“网络超时”,这时需更贴近真实流程。
- 在 mock 中创建
AbortController,调用abort()模拟中断 - 让 mock 的 fetch/axios 返回一个立即被 abort 的 Promise:
const controller = new AbortController(); controller.abort(); return fetch(url, { signal: controller.signal }); - 这样被测代码收到的就是标准
DOMException(name: 'AbortError'),能准确命中if (err.name === 'AbortError')判断
验证超时后的业务响应
只 mock 超时还不够,必须检查代码是否按设计做出反应。
- 重试逻辑:mock 第一次超时、第二次成功,断言请求函数被调用了两次,且最终状态/返回值正确
- UI 状态更新:检查是否设置了
isLoading = false、errorText = '请求超时,请重试'等字段 - 兜底行为:超时后是否读取缓存数据、展示离线内容或 fallback 组件
- 日志或上报:用
jest.spyOn(console, 'warn')或 mock 上报函数,确认超时事件被记录
避免常见误区
有些做法看似合理,实则不可靠或引入额外复杂度。
- 不用
jest.useFakeTimers()控制 fetch 时间——它对原生 fetch/axios 无效,只影响setTimeout类 API - 不依赖真实网络或代理工具(如 node-mitm)做单元测试——太重、不稳定、难断言
- 不只检查“有没有抛错”,而要覆盖完整路径:超时 → 清理 loading → 显示提示 → 触发重试按钮可用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











