如何配置Surefire插件,在Maven项目中运行非公开测试类?
解决Java模块项目中非public测试类/方法的Surefire执行问题
这个问题本质是**Java模块系统(JPMS)**和早期版本的Surefire插件兼容性不足导致的——旧版本的Surefire在处理模块内非public测试类时,无法正确通过反射访问,触发了InaccessibleObjectException。下面是几个靠谱的解决方案,按推荐度排序:
方案1:升级Surefire插件和JUnit Jupiter版本(最推荐)
早期的maven-surefire-plugin:3.0.0-M5对JPMS的支持还不够完善,后续版本已经修复了非public测试的访问问题。建议直接升级到稳定兼容的版本组合:
示例POM配置
<!-- 构建插件部分 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- 推荐使用3.1.0+的稳定版 --> <version>3.1.2</version> </plugin> </plugins> </build> <!-- 依赖部分 --> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <!-- 与Surefire 3.1.x兼容的JUnit版本,推荐5.9.x+ --> <version>5.9.2</version> <scope>test</scope> </dependency> </dependencies>
升级后,Surefire会自动处理JPMS模块内的非public测试类/方法,无需修改测试代码或模块配置,直接执行mvn test即可正常运行。
方案2:调整模块描述符开放测试包
如果暂时无法升级版本,可以修改module-info.java,将测试所在的包开放给JUnit和Surefire相关模块,允许它们通过反射访问非public类:
示例module-info.java配置
// 方式1:开放整个模块给所有测试相关模块(简单但权限稍大) open module sample.core { requires org.junit.jupiter.api; } // 方式2:精准开放指定包给特定模块(更安全) module sample.core { requires org.junit.jupiter.api; // 开放测试包给JUnit平台、JUnit引擎和Surefire的JUnit平台适配器 opens org.sample to org.junit.platform.commons, org.junit.jupiter.engine, org.apache.maven.surefire.junitplatform; }
这种方式需要手动维护模块权限,后续如果更换测试框架或插件版本,可能需要调整开放的模块列表。
方案3:临时关闭模块系统(不推荐)
如果是单模块项目且对JPMS特性依赖不高,可以通过Maven编译插件参数临时关闭模块系统,让测试运行在传统的类路径模式下:
示例POM配置
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <compilerArgs> <!-- 关闭模块系统,使用类路径模式 --> <arg>--no-module-directories</arg> </compilerArgs> </configuration> </plugin>
⚠️ 注意:这个方案会丢失JPMS的模块隔离优势,仅适合临时应急场景。
内容的提问来源于stack exchange,提问作者diziaq




