Java 9 + maven + junit:测试代码是否需要自己的module-info.java以及放置它的位置?

Rom*_*kiy 32 java junit maven java-9 java-module

假设我有一个使用Maven 3和junit的Java项目.有src/main/javasrc/test/java目录分别包含主要来源和测试来源(一切都是标准的).

现在我想将项目迁移到Java 9. src/main/java内容代表Java 9模块; 有com/acme/project/module-info.java看大约是这样的:

module com.acme.project {
    require module1;
    require module2;
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果测试代码需要module-info.java自己怎么办?例如,添加对某些模块的依赖性,该模块仅用于测试,而不是生产代码.在这种情况下,我必须把module-info.javasrc/test/java/com/acme/project/给模块不同的名称.这样Maven似乎将主要源和测试源视为不同的模块,因此我必须将包从主模块导出到测试模块,并且需要测试模块中的包,如下所示:

主模块(in src/main/java/com/acme/project):

module prod.module {
    exports com.acme.project to test.module;
}
Run Code Online (Sandbox Code Playgroud)

测试模块(in src/test/java/com/acme/project):

module test.module {
    requires junit;
    requires prod.module;
}
Run Code Online (Sandbox Code Playgroud)

这产生了

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:testCompile (default-testCompile) on project test-java9-modules-junit: Compilation failure: Compilation failure:
[ERROR] /home/rpuch/git/my/test-java9-modules-junit/src/test/java/com/acme/project/GreeterTest.java:[1,1] package exists in another module: prod.module
Run Code Online (Sandbox Code Playgroud)

因为一个包在两个模块中定义.所以现在我必须在主模块和测试模块中有不同的项目,这是不方便的.

我觉得我走错了道路,一切都开始看起来非常难看.如何module-info.java在测试代​​码中拥有自己的代码,或者如何在没有测试代码的情况下实现相同的效果(require等)?

man*_*uti 9

该模块系统不之间的生产代码和测试代码区分,因此,如果选择模块化测试的代码中,prod.module并且test.module不能共享相同的包com.acme.project,如在所描述的功能:

无干扰 - Java编译器,虚拟机和运行时系统必须确保包含相同名称的包的模块不会相互干扰.如果两个不同的模块包含相同名称的包,那么从每个模块的角度来看,该包中的所有类型和成员仅由该模块定义.一个模块中该包中的代码必须不能访问另一个模块中该包中的包私有类型或成员.

如Alan Bateman所示,Maven编译器插件在编译src/test/java树中的代码时使用--patch-module和模块系统提供的其他选项,以便测试模块使用测试类进行扩充.在运行测试类时,这也是由Surefire插件完成的(请参阅命名Java 9模块中的支持运行单元测试).这意味着您无需将测试代码放在模块中.

  • 更改软件包以进行测试具有不利之处,即您的测试将不再达到默认值和受保护的修饰符。 (2认同)
  • 该模块提供了--patch-module和其他选项,以支持编译和执行与被测模块位于同一程序包/模块中的测试。当在src / test树中编译代码时,maven-compiler-plugin使用这些选项。同样适用于surefire插件。 (2认同)
  • @nullpointer 它似乎添加在 https://issues.apache.org/jira/browse/SUREFIRE-1420 中。 (2认同)

Nam*_*man 7

您可能想要重新考虑您尝试实施的项目设计.由于您正在将一个模块及其测试实现到项目中,因此您应该避免为每个模块单独使用不同的模块.

module-info.java模块及其相应的测试应该只有一个单独的.

您的相关项目结构可能如下所示: -

Project/
|-- pom.xml/
|
|-- src/
|   |-- test/
|   |   |-- com.acme.project
|   |   |        |-- com/acme/project
|   |   |        |      |-- SomeTest.java
|   |   
|   |-- main/
|   |   |-- com.acme.project
|   |   |    |-- module-info.java
|   |   |    |-- com/acme/project
|   |   |    |    |-- Main.java
Run Code Online (Sandbox Code Playgroud)

其中module-info.java可能进一步是: -

module com.acme.project {
    requires module1;
    requires module2;
    // requires junit; not required using Maven
}
Run Code Online (Sandbox Code Playgroud)

只是根据你的问题总结以上所有内容 -

我觉得我走错了道路,一切都开始看起来非常难看.我如何在测试代码中拥有自己的module-info.java,或者如何在没有测试代码的情况下实现相同的效果(需要等)?

是的,您不应该考虑为测试代码管理不同的模块,使其变得复杂.

通过使用如下指令将处理junit编译时依赖性,可以实现类似的效果-

requires static junit;
Run Code Online (Sandbox Code Playgroud)

使用Maven,您可以按照上述结构实现此目的,并使用maven-surefire-plugin它来处理将测试单独修补到模块.

  • 在模块描述符中要求`junit`对我来说看起来不是很好 (3认同)