如何在Maven JPMS项目中避免测试依赖混入生产Jar包?
解决JPMS下测试依赖侵入生产模块的问题
你的场景很典型:生产代码仅定义SQL常量字符串,完全不需要java.sql模块,但测试代码用到了java.sql API和HSQLDB,启用JPMS后误以为生产模块必须声明requires java.sql,导致不必要的依赖进入生产Jar。这里有几个可行的解决办法:
1. 为测试代码单独配置模块描述符
在测试源码目录(src/test/java)下创建独立的module-info.java,专门用于测试模块的依赖声明:
- 生产模块的
src/main/java/module-info.java不要添加requires java.sql,因为生产代码根本没有引用java.sql包下的任何类 - 测试模块的
module-info.java按需声明依赖,示例:
module test.unittest { requires java.sql; requires test; // 依赖你的生产模块 requires org.hsqldb; // 若HSQLDB是模块化依赖,按需添加 }
Maven会自动区分主源码和测试源码的模块描述符,编译生产代码时仅使用src/main/java下的配置,测试编译则用测试目录的配置,这样生产Jar的模块信息里不会混入测试相关的依赖。
2. 确认生产代码无java.sql依赖
仔细检查生产代码Test.java:如果只是定义SQL字符串常量,没有导入java.sql.*下的任何类(比如Connection、Statement等),那么JPMS根本不会强制要求生产模块声明requires java.sql。之前的困惑可能是IDE误报或者对JPMS规则的误解,只要生产代码没用到,就不需要加这个声明。
3. 用requires static处理间接编译依赖(若有)
如果生产代码存在间接的编译期依赖(比如通过第三方库间接引用,但运行时完全不需要),可以在生产模块的module-info.java中使用:
requires static java.sql;
requires static表示该依赖仅在编译阶段生效,不会被标记为模块的运行时依赖,生产Jar的模块信息里虽然有这个声明,但不会强制要求运行时环境提供java.sql模块,也不会影响生产包的依赖范围。
额外注意事项
- 确保HSQLDB的Maven依赖范围是
test,这样它不会被打包进生产Jar:
<dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <scope>test</scope> </dependency>
- 编译时Maven的
maven-compiler-plugin会分别处理主源码和测试源码的模块配置,无需额外配置即可区分生产和测试的依赖。
内容的提问来源于stack exchange,提问作者Grim
相关产品推荐
相关产品推荐

