异步并发请求测试需主动控制节奏、验证限流与并行性、错误隔离及结果聚合:用带ID和日志的mock任务、runningCount计数器、jest.useFakeTimers()分步推进,断言并发数不超限,覆盖全成功、部分失败、空输入等场景,并通过压力测试暴露隐式串行问题。

测试异步并发请求,关键不是“等结果出来再断言”,而是主动控制执行节奏、观测并发行为、验证聚合逻辑。重点在于:限流是否生效、任务是否真正并行(而非串行伪装)、错误是否隔离、最终结果是否可预期。
用可控 mock 任务代替真实请求
避免依赖网络或定时器带来的不确定性:
- 写几个带 ID 和日志的 Promise 工厂函数,例如 mockTask(id, delay = 100, shouldReject = false),内部用
setTimeout或Promise.resolve().then()控制时机 - 每个任务开始时记录进入时间、ID,并递增运行计数器;结束时递减计数器并记录退出时间
- 故意让第 2 个和第 5 个任务 reject,用于验证错误不影响其他任务执行
断言并发数是否被准确限制
这是最容易忽略但最核心的一环:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 在每个 mock 任务内部插入断言:expect(runningCount).toBeLessThanOrEqual(maxConcurrency)
- 配合 Jest 的
jest.useFakeTimers(),用jest.advanceTimersByTime(100)分步推进,观察计数器是否始终未超限 - 任务全部结束后,用
await waitFor(() => expect(runningCount).toBe(0))确保无残留
验证结果聚合与错误传播行为
队列返回值通常是 Promise 或 Promise,需覆盖多种组合:
- 全成功:检查数组长度匹配输入数量、各元素 result.id 是否与原始 task id 一一对应(若保证顺序)
- 部分失败:确认是否抛出
AggregateError,且error.errors包含全部失败原因;其余成功项结果仍应存在 - 空数组输入:应立即 resolve,不触发任何任务
- 设
maxConcurrency = 1时,应退化为严格串行,可用作基准对照
构造压力场景验证边界可靠性
单元测试要能暴露“看似正常、实则脆弱”的问题:
- 传入 30 个任务,
maxConcurrency = 4,检查日志中是否稳定出现“4 个同时 start → 4 个陆续 end → 下一批 4 个 start”模式 - 让第 7 个任务 reject,观察第 8–10 个是否照常启动(说明错误未阻塞队列调度)
- 用
performance.now()记录总耗时,对比理论最小值(如 30 个 × 100ms / 并发 4 ≈ 750ms),偏差过大说明有隐式串行或锁竞争
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










