
JUnit 5 的 maven-surefire-plugin 版本不匹配导致测试不执行
现象是 mvn test 没报错但完全跳过测试,或者提示 No tests found。根本原因常是 Surefire 插件太老,不支持 JUnit 5 的引擎发现机制。
必须用 maven-surefire-plugin 2.22.0 及以上版本,并显式配置 junit-jupiter 作为 provider:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M9</version>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
- 旧版(如 2.12)默认只认
JUnit4Provider,即使写了@Test注解也不会触发 JUnit 5 运行器 - 别信 IDE 自带的 Maven 嵌入版本——命令行跑
mvn -v看实际用的是哪个 Maven,再确认插件绑定的版本 - 如果项目还混用 JUnit 4 测试,得加
junit-vintage-engine依赖,否则老测试直接被忽略
Gradle 中忘记声明 testImplementation 导致 ClassNotFoundException
运行时抛 java.lang.ClassNotFoundException: org.junit.jupiter.api.Test,不是因为没下 JUnit,而是依赖没进 test classpath。
Gradle 默认把 implementation 依赖只加到 main 编译路径,test 类根本看不到 JUnit 类:
立即学习“Java免费学习笔记(深入)”;
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
}
-
testImplementation是必须的——它让 JUnit API 在 test 编译期可见;testRuntimeOnly让 engine 在运行期可用 - 用
compileOnly或api都不行,前者编译不过,后者污染 main 路径且 runtime 不加载 engine - IntelliJ 有时会自动补全成
implementation,手敲务必核对前缀
IDEA 里右键 Run Test 却启动了 JUnit 4 运行器
明明代码用的是 @org.junit.jupiter.api.Test,但 IDEA 显示 “Using JUnit 4 runner”,点进去看堆栈全是 junit.framework 包路径。
这是 IDEA 缓存了旧的测试配置,或项目未正确识别 JUnit 5 为默认测试框架:
- 删掉项目根目录下的
.idea/misc.xml和.idea/workspace.xml(关掉 IDEA 再删),重启后重新导入 Maven/Gradle 项目 - 检查
File → Project Structure → Libraries,确认junit-jupiter-api和junit-jupiter-engine已加载,且没有冲突的junit-4.xjar - 单个测试类右键 Run 时,留意弹出菜单里是不是有 “JUnit5” 选项——如果没有,说明 IDEA 根本没解析出注解,大概率是依赖或插件问题先于 IDE 配置
@ExtendWith 和 @RegisterExtension 混用引发 ExtensionConfigurationException
想给测试加日志或数据库清理逻辑,加了自定义 Extension,但一跑就崩在 ExtensionConfigurationException: Extension must be @ExtendWith or @RegisterExtension。
这个错不是语法错,是生命周期冲突:一个 extension 不能既被 @ExtendWith 声明为全局,又被 @RegisterExtension 实例化为字段。
-
@ExtendWith(MyExt.class)作用于类或方法,每次测试都新建实例;@RegisterExtension MyExt ext = new MyExt()是字段级,实例由测试类持有,可复用、可设断点调试 - 二者不能同时出现在同一个测试类上——IDEA 有时会自动补全
@ExtendWith,但你又手动 new 了字段,就会撞车 - 如果 extension 需访问测试实例(比如读取
@TestInfo),只能用@RegisterExtension字段方式;纯静态行为(如设置系统属性)两种都行
最常被忽略的是:JUnit 5 的 extension 执行顺序严格依赖声明位置和注解类型,字段注册的 extension 总比类级 @ExtendWith 更早初始化——这点不注意,mock 或 DB 清理就可能失效。









