@RepeatedTest是JUnit5用于重复执行测试方法的注解,仅支持单线程顺序执行,适用于随机性验证或稳定性检查,但不支持并发、吞吐量统计等压力测试功能。

@RepeatedTest 是 JUnit 5 提供的注解,用于**重复执行同一个测试方法多次**,但它**不是为压力测试(如高并发、吞吐量、响应时间监控)设计的**。它适合做简单场景验证(比如随机输入、状态不确定性检查),但不能替代专业的压力测试工具(如 JMeter、Gatling)或并发测试框架(如 CompletableFuture + 多线程模拟)。
理解 @RepeatedTest 的定位和限制
它只是在单线程下顺序执行 N 次测试方法,每次都是独立的测试实例(会重新创建测试类实例、执行 @BeforeEach 等),不涉及:
- 多线程/并发调用
- 请求计时、吞吐量统计、错误率计算
- 资源预热、JVM 预热、GC 干扰控制
- 外部系统(如数据库、HTTP 服务)的压力隔离与监控
所以,别指望靠 @RepeatedTest(times = 1000) 就能测出接口 QPS 或发现线程安全问题。
正确使用 @RepeatedTest 的典型场景
适用于需要「多次运行以暴露偶然性缺陷」的轻量级验证,例如:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 测试含随机逻辑的方法(如 UUID 生成、随机数校验)
- 验证幂等操作是否真正稳定(如某次更新后状态始终一致)
- 配合
Assumptions做条件跳过,避免偶发环境失败影响 CI - 快速验证修复后的偶发 NPE 是否消失(连续跑 50 次不崩)
示例:
@RepeatedTest(10)
void shouldNotThrowWhenProcessingRandomInput() {
String input = RandomStringUtils.randomAlphabetic(5, 10);
assertDoesNotThrow(() -> processor.handle(input));
}
如果真想做压力测试,该怎么做?
JUnit 不是压力测试框架。推荐组合方案:
-
单机小规模并发模拟:用
ExecutorService+CountDownLatch或CompletableFuture.allOf()启动多线程调用目标方法,手动记录耗时、异常数 - 标准压测流程:用 JMeter 写脚本,配置线程组、RPS 控制、监听器(聚合报告、响应时间图),连接被测服务的 REST/HTTP 接口
-
集成到单元测试流程中(谨慎):写一个
@Test方法,在里面启动 100 个线程循环调用业务方法,用System.nanoTime()统计平均耗时——仅限开发自测,勿进 CI 主流程 - 关注 JVM 层面:配合 JFR(Java Flight Recorder)或 VisualVM,观察重复调用下的内存分配、GC 行为、锁竞争
一个小提醒:别在 @RepeatedTest 里做重操作
因为它是顺序执行,1000 次重复 ≈ 串行执行 1000 遍,容易让单测变慢、掩盖真实问题。例如:
- 每次重复都连一次数据库?→ 改用内存 H2 +
@BeforeEach初始化数据 - 每次重复都发一次 HTTP 请求?→ 改用 WireMock 模拟,或直接测试 Service 层
- 重复中依赖时间(如
new Date())?→ 使用可注入的 Clock 或 TimeProvider,便于控制时间流
否则,你的“重复测试”可能只是在测网络抖动或数据库连接池耗尽,而不是代码逻辑。

















