测试 promise.all 并发逻辑需 mock 每个被包裹的异步函数,分别控制其 resolved/rejected 状态、延迟与时序,验证成功、部分失败、全部失败及超时等场景,禁用直接 mock promise.all 或全同步 resolve。

测试依赖 Promise.all 的并发异步逻辑,核心是**控制 Promise 的 resolved/rejected 状态、时序和数量**,确保能覆盖成功、部分失败、全部失败、超时等关键路径。不能只 mock 返回值,还要模拟并发行为本身。
精准 mock 每个 Promise 的行为
不要直接 mock Promise.all 整体返回值——这会绕过并发逻辑验证。应 mock 被 Promise.all 包裹的每个异步调用(如 API 函数),让它们返回可控的 Promise:
- 用
jest.fn()替换原始函数,返回Promise.resolve(data)、Promise.reject(error)或带延迟的 Promise - 对多个调用分别设置不同响应:一个 resolve,一个 reject,一个延迟 500ms 后 resolve
- 示例:
api.getUser.mockResolvedValue({ id: 1 }); api.getOrder.mockRejectedValue(new Error('timeout'));
验证 Promise.all 的聚合行为是否符合预期
Promise.all 一旦有任意 Promise reject,就立即 reject,不会等待其余完成。测试需明确断言这一特性:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 当某一项 reject 时,主逻辑应捕获该错误,且不依赖其他未完成的 Promise 结果
- 用
await expect(...).rejects.toThrow(...)验证整体被拒绝,再检查错误是否来自预期项 - 若业务允许“软失败”,可改用
Promise.allSettled并测试 fulfilled/rejected 混合结果结构
测试超时与竞态条件
真实并发中常配合 AbortController 或封装 timeout,测试时要触发边界情况:
- 手动构造一个长期 pending 的 Promise(如
new Promise(() => {})),验证 timeout 逻辑是否如期中断 - 用
jest.useFakeTimers()控制时间流逝,快速触发超时判定 - 检查清理逻辑是否执行(如取消未完成请求、释放资源)
避免常见陷阱
很多测试看似通过,实则没测到并发本质:
- ❌ 不要 mock
Promise.all本身(如jest.mock('promise-all', ...)),失去对并发调度的验证 - ❌ 不要让所有 mock Promise 同步 resolve,这退化为同步执行,无法暴露竞态或错误传播问题
- ✅ 在测试前后用
jest.clearAllMocks()和jest.restoreAllMocks()保证隔离性 - ✅ 断言最终状态时,同时检查数据内容、调用次数、参数顺序,确认并发发起正确
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










