必须添加 junit-vintage-engine 才能运行 JUnit 4 测试,因其是 JUnit 5 平台加载 JUnit 4 测试的运行时适配器;需用 testRuntimeOnly 声明、版本与 Jupiter 对齐,并在 Spring Boot 2.4+ 中手动取消排除。

Gradle 项目里加 junit-vintage-engine 才能识别 JUnit 4 测试
Gradle 默认只认 junit-jupiter,不带 vintage 引擎的话,@Test 来自 org.junit.Test 的类会被直接跳过,连编译都可能报错 NoClassDefFoundError: org/junit/Test。
必须显式引入 vintage 引擎,且版本要和 Jupiter 对齐(比如都用 5.10.2):
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.2' testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.10.2'
注意:testRuntimeOnly 是关键。vintage 引擎不是写测试用的 API,而是运行时加载 JUnit 4 测试的“翻译器”,放错 scope 就会失效。
- Spring Boot 2.4+ 默认把
junit-vintage-engine排除掉了,如果用了 Spring Boot,得在build.gradle里手动取消排除 - 别同时拉
junit:junit:4.13.2和junit-vintage-engine—— 前者是 JUnit 4 自身的 jar,后者才是让它跑在 JUnit 5 平台上的适配层;混着加容易触发类加载冲突
测试类路径和命名不能乱,否则 Gradle 找不到
Gradle 的 test 任务默认只扫描 src/test/java 下符合命名规范的类。JUnit 4 和 JUnit 5 的测试类都得遵守同一套发现规则,否则一个都跑不起来。
立即学习“Java免费学习笔记(深入)”;
- 测试类必须放在
src/test/java,不能放在src/main/java或其他目录 - 类名建议以
Test结尾(如UserServiceTest),否则某些旧版插件或 CI 配置可能跳过 - 类不能是
final或private,否则 JUnit Platform 反射实例化失败,报Cannot invoke a non-static inner class without an enclosing instance
常见错误现象:命令行执行 ./gradlew test 输出 “No tests found”,但 IDE 里点运行却能看到结果——大概率是路径或类修饰符错了,IDE 没走 Gradle 的标准发现逻辑。
运行时指定 --tests 参数要小心包名和方法名格式
--tests 参数对 JUnit 4 和 JUnit 5 的匹配方式一致,但实际行为取决于底层引擎是否加载成功。如果 vintage 没生效,哪怕你写了 --tests com.example.MyLegacyTest,也会静默忽略。
- 匹配整个类:
./gradlew test --tests "com.example.*"(引号防止 shell 展开) - 匹配某个 JUnit 4 方法:
./gradlew test --tests "com.example.MyLegacyTest.testSaveUser"—— 注意方法名是 JUnit 4 风格,不用改注解 - JUnit 5 的
@ParameterizedTest方法也能被识别,只要 vintage 引擎已加载,不会干扰
性能影响:双引擎并存会让测试启动稍慢(多加载一个引擎),但单次执行耗时几乎无差别。真正拖慢的是混合项目中因依赖冲突导致的重复编译或 classpath 冗余。
IDE 同步失败时优先检查 Delegate to Build Tool 设置
IntelliJ 和 Eclipse 经常用自己的测试运行器加载类,绕过 Gradle 配置的 junit-vintage-engine,结果就是 IDE 能跑 JUnit 4,命令行却不行,或者反过来。
IntelliJ 用户必须确认:Settings > Build > Build Tools > Gradle > Runner 中勾选了 Delegate IDE build/run actions to Gradle。没勾的话,IDE 用自己 ClassLoader 加载,junit-vintage-engine 根本不参与。
- 改完设置后要重启 IDE,否则缓存还在用旧 classpath
- 如果用了 TestNG 或 Spock 插件,它们可能劫持测试发现流程,得关掉或调低优先级
最隐蔽的问题是:vintage 引擎加载失败时,Gradle 不报错,只是安静地跳过所有 JUnit 4 类。所以看到 “0 tests executed” 时,第一反应不该是删代码,而是检查 testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' 是否真的进了 classpath,以及有没有被其他依赖意外 exclude。


















