为何ServiceLoader.load(...)运行正常但Maven测试失败?
问题解决:Maven测试时ServiceLoader无法找到JPMS提供的实现
核心原因
Maven Surefire插件默认可能未启用**模块路径(Module Path)**模式,导致测试时忽略了module-info.java中的uses/provides声明,转而用传统类路径方式运行,使得JPMS的服务发现机制失效。而IDE会自动处理模块上下文,所以运行正常。
解决方案
1. 升级并配置Surefire插件
确保使用支持JPMS的最新版Surefire插件,并强制启用模块路径:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> <!-- 推荐使用最新稳定版 --> <configuration> <!-- 强制使用模块路径运行测试 --> <useModulePath>true</useModulePath> <!-- 测试时临时导出内部包给web模块(如果测试代码需要访问的话) --> <addModuleExports> <addModuleExport>com.sample.domain/com.sample.domain.internal=com.sample.web</addModuleExport> </addModuleExports> </configuration> </plugin> </plugins> </build>
2. 验证测试模块的声明
如果你的测试代码有独立的module-info.test.java,需要确保它包含:
module com.sample.web.test { requires com.sample.domain; uses com.sample.domain.api.UseCase; // 其他测试相关依赖 }
如果是使用open module,也要保证测试模块的配置兼容。
3. 确认模块依赖的正确性
在com.sample.web的pom.xml中,确保com.sample.domain的依赖是模块依赖而非普通JAR依赖:
<dependency> <groupId>com.sample</groupId> <artifactId>domain</artifactId> <version>${project.version}</version> </dependency>
4. 备选:显式指定ServiceLoader的模块上下文
如果上述配置仍有问题,可以在测试代码中显式指定模块层:
@Bean UseCase useCase() { // 显式使用启动模块层来加载服务 return ServiceLoader.load(ModuleLayer.boot(), UseCase.class) .findFirst() .orElseThrow(); }
内容的提问来源于stack exchange,提问作者energize-cactus
相关产品推荐
相关产品推荐

