异步测试中验证错误重试逻辑应通过 mock 控制失败次数与时机,断言调用次数、参数一致性及延迟行为,并覆盖耗尽重试、首次成功、零重试等边界场景,推荐依赖注入而非全局 patch。

在异步测试中验证错误重试逻辑,关键不是“等它重试完”,而是用可控的模拟行为让重试过程可观察、可断言。
用 mock 控制失败次数与时机
不要依赖真实网络或定时器。用 jest.fn() 创建一个返回 Promise 的 mock 函数,让它按需 resolve 或 reject:
- 前 n 次调用 返回
Promise.reject(new Error('timeout')) - 第 n+1 次调用 返回
Promise.resolve({ data: 'ok' }) - 确保每次 reject 都是新 error 实例(避免引用相等导致意外缓存)
断言调用次数和顺序
重试 n 次意味着函数被调用了 n+1 次(首次 + n 次重试):
- 调用被测函数后,检查
mockFn.mock.calls.length === expectedRetryCount + 1 - 可进一步断言每次调用的参数是否一致(如 URL、headers 是否未被意外修改)
- 若重试逻辑含延迟(如
setTimeout),配合jest.useFakeTimers()和jest.runAllTimers()验证延迟是否触发
覆盖典型边界场景
只测“成功重试”不够,还要验证异常路径是否按预期处理:
- 耗尽重试仍失败:mock 始终 reject,断言最终抛出错误,且调用次数 = maxRetries + 1
- 首次就成功:mock 直接 resolve,断言调用次数为 1,无延迟或重试行为
-
零重试配置:传入
maxRetries: 0,应仅执行一次,不进入任何等待逻辑
推荐依赖注入而非全局 patch
避免 mock 全局 fetch 或 setTimeout,容易引发测试污染或难以隔离:
- 把异步操作函数(如
fetch)作为参数传入被测函数,或通过构造器注入 - 测试时传入自定义 mock,完全掌控其行为,无需担心环境干扰
- 例如:
await fetchWithRetry('/api', { fetch: mockFetch, maxRetries: 2 })
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











