枚举定义策略、countdownlatch 控制并发节奏是java单测中兼顾可读性与可控性的常用组合:枚举实现统一接口封装策略逻辑,countdownlatch通过startlatch和donelatch协调多策略并行执行与统一等待,配合线程安全隔离确保测试可靠性。

用枚举定义策略、用 CountDownLatch 控制并发节奏,是 Java 单测中兼顾可读性与可控性的常用组合。核心不是“枚举本身支持并发”,而是把枚举作为策略容器,配合 CountDownLatch 实现多策略并行触发 + 统一等待。
用枚举封装策略逻辑
枚举天然适合定义有限、明确的业务策略。每个枚举项可携带独立行为,避免 if-else 或反射调用:
- 定义枚举时让其实现统一接口(如 Strategy),声明 execute() 方法
- 每个枚举常量重写该方法,内聚各自逻辑(比如 mock 不同支付渠道、模拟不同风控规则)
- 测试中通过 Strategy.values() 获取全部策略,或按需选取子集
CountDownLatch 控制并发起点与终点
单测中要真实模拟“多个策略同时生效”,不能靠循环串行执行。需要两个 latch:
- startLatch = new CountDownLatch(1):所有策略线程启动后都 await(),等主线程发令才真正开始执行
- doneLatch = new CountDownLatch(strategies.length):每个策略执行完调用 countDown(),主线程 await() 等全部完成再断言
在 JUnit 中组装测试流程
以 JUnit 5 为例,典型结构如下:
- 测试方法内初始化两个 latch,构建策略数组(如 PaymentStrategy.values())
- 为每个策略创建一个 Runnable:先 await(startLatch),再 execute(),最后 doneLatch.countDown()
- 用 Executors.newFixedThreadPool(n) 启动线程(线程数建议 ≤ 策略数,避免资源争抢干扰结果)
- 主线程 sleep 模拟“准备就绪”,再 startLatch.countDown();随后 doneLatch.await() 等待全部结束
- 校验共享状态(如统计 map、数据库记录、mock 验证次数)是否符合多策略并发预期
注意线程安全与副作用隔离
并发单测失败常因状态污染。关键细节:
- 策略间共享的测试对象(如 mock service、in-memory repository)必须线程安全,或每个线程使用独立实例
- 避免静态变量、单例 bean 在测试中被多线程修改——JUnit 默认每个 test method 新建实例,但 static 成员仍全局可见
- 若策略涉及外部依赖(如 HTTP 调用),务必用 WireMock 或 TestRestTemplate 替代真实请求,保证可重复性和速度











