在具有模块间测试依赖项的 Maven 版本中正确实现 Java 模块
我有一个使用Maven和Java的多模块项目。我现在正试图迁移到Java 9/10/11并实现模块(如JSR 376:Java Platform Module System,JPMS)。由于该项目已经由Maven模块组成,并且依赖项是直接的,因此为项目创建模块描述符非常简单。
现在,每个 Maven 模块在文件夹中都有自己的模块描述符 ()。测试类没有模块描述符。module-info.java
src/main/java
但是,我偶然发现了一个我无法解决的问题,并且没有找到有关如何解决的任何描述:
如何与 Maven 和 Java 模块建立模块间测试依赖关系?
在我的情况下,我有一个“通用”Maven模块,其中包含一些接口和/或抽象类(但没有具体的实现)。在同一个 Maven 模块中,我有抽象测试来确保这些接口/抽象类实现的正确行为。然后,有一个或多个子模块,其中包含接口/抽象类的实现和扩展抽象测试的测试。
但是,当尝试执行 Maven 构建的阶段时,子模块将失败,并显示:test
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:testCompile (default-testCompile) on project my-impl-module: Compilation failure: Compilation failure:
[ERROR] C:\projects\com.example\my-module-test\my-impl-module\src\test\java\com\example\impl\FooImplTest.java:[4,25] error: cannot find symbol
[ERROR] symbol: class FooAbstractTest
[ERROR] location: package com.example.common
我怀疑发生这种情况是因为测试不是模块的一部分。即使 Maven 做了一些“魔术”来让测试在模块范围内执行,它也不适用于我所依赖的模块中的测试(出于某种原因)。如何解决此问题?
项目的结构如下所示(此处提供完整的演示项目文件):
├───my-common-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───common
│ │ │ ├───AbstractFoo.java (abstract, implements Foo)
│ │ │ └───Foo.java (interface)
│ │ └───module-info.java (my.common.module: exports com.example.common)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───common
│ └───FooAbstractTest.java (abstract class, tests Foo)
├───my-impl-module
│ ├───pom.xml
│ └───src
│ ├───main
│ │ └───java
│ │ ├───com
│ │ │ └───example
│ │ │ └───impl
│ │ │ └───FooImpl.java (extends AbstractFoo)
│ │ └───module-info.java (my.impl.module: requires my.common.module)
│ └───test
│ └───java
│ └───com
│ └───example
│ └───impl
│ └───FooImplTest.java (extends FooAbstractTest)
└───pom.xml
中的依赖关系如下:my-impl-module/pom.xml
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common-module</artifactId>
<classifier>tests</classifier> <!-- tried type:test-jar instead, same error -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
注意:以上只是我为演示问题而创建的项目。真正的项目要复杂得多,在这里可以找到(主分支还没有模块化),但原理是一样的。
PS:我不认为代码本身有什么问题,因为所有内容都使用正常的类路径(即在IntelliJ中,或没有Java模块描述符的Maven)进行编译和运行。Java 模块和模块路径引入了此问题。