并发控制器测试需验证三方面:一是严格限制并发数(如limit=3),通过计数器或时间线确保任一时刻运行任务≤limit;二是动态补位,耗时差异任务队列中,任一任务结束即刻启动下个;三是异常场景,包括失败不阻塞、动态追加任务、空/零限边界处理。

测试并发异步任务流,核心是验证控制器能否按设定的并发数(如 limit = 3)正确调度任务:不超限执行、空闲时及时补位、结果顺序/完整性符合预期。不能只测“能跑”,要测“控得准”。
验证并发数是否被严格执行
这是最基础也最关键的断言。启动远超 limit 的任务(比如 10 个),用 Promise.allSettled 收集全部结果,再检查实际并发峰值。
- 在每个任务开始和结束时打日志或记录时间戳(例如用
console.time('task-1')/console.timeEnd('task-1')) - 分析时间线:任意时刻正在运行中的任务数不应超过 limit;第 4 个任务的启动时间应晚于前 3 个中最早完成的那个
- 更稳妥的做法是注入一个计数器,在任务体内部增减,并在每次变化时断言
currentConcurrent ≤ limit
测试任务排队与动态补位逻辑
并发控制器不是“一次配置终身有效”,它必须响应任务完成并立即拉取下一个。重点验证“空档期”是否被填满。
- 准备一组耗时差异大的任务(例如:[200ms, 800ms, 100ms, 500ms]),加入队列
- 记录每个任务的 start time 和 end time
- 检查:第 1 个任务结束后,第 4 个任务是否紧随其后启动(而非等待第 2 或第 3 个)?这说明队列是 FIFO + 即时调度,不是固定分组
- 可配合
jest.useFakeTimers()加速验证,避免真实等待
覆盖边界与异常场景
真实环境里,任务会失败、会中途取消、会动态添加新任务。只测全成功是片面的。
-
失败传播:让某个任务
reject,确认它不会阻塞后续任务,且错误能被单独捕获(例如Promise.allSettled返回中对应项为{ status: 'rejected', reason }) -
动态追加:在初始 5 个任务已提交、其中 2 个还在运行时,再调用
addTask,验证新任务是否进入队列并在资源释放后执行 -
零任务或超限任务:传入空数组、或
limit = 0,检查行为是否符合设计(如直接 reject、静默忽略,或抛出明确错误)
避免常见陷阱
很多测试看似通过,实则没测到并发本质。
- 别用
await串行调用任务——那测的是单线程顺序,不是并发调度 - 别依赖
setTimeout模拟延迟而不控制时间精度,容易因时序抖动导致偶发失败;优先用jest.advanceTimersByTime() - 不要只断言“所有任务都完成了”,要断言“它们是以受控并发的方式完成的”——前者是功能正确性,后者才是控制器的价值
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











