Eclipse m2e不支持JPMS模块的Maven测试罐

时间:2018-11-14 21:24:04

标签: java eclipse maven m2e module-info

我有一个项目“ java11-core”,该项目生成一个测试jar工件以与项目“ java11-app”共享。这些项目可以使用命令行Maven很好地构建,但是在Eclipse中,找不到在测试jar中共享的类。

版本信息:

  • Apache Maven 3.6.0(命令行和Eclipse)
  • Java版本:11.0.1,供应商:Oracle Corporation
  • Eclipse IDE:版本:2018-09(4.9.0)
  • M2E插件:1.9.1.20180912-1601

我最初将这些项目创建为传统的非JPMS项目。这些项目通常按预期进行编译和运行测试。在将module-info.java添加到java11-core和java11-app后,Eclipse编译器无法识别核心项目中的共享测试文件。

这里是程序包浏览器的快照,以概述项目结构。

enter image description here

分别添加了java11-app和java11-core module-info内容:

module com.java11.app {

    exports com.java11.app;
    requires com.java11.core;
}

module com.java11.core {

    exports com.java11.core;
}

如您所见,我没有从com.java11.core中导出测试实用程序包。我不想导出测试包,因为这会使测试类公开可用。我也不想引入一个新的测试项目,因为在实际情况下,这很可能需要测试实用程序与其协助测试的项目之间的循环依赖。

enter image description here

在AppTest.java中生成错误。 Eclipse报告的失败很有趣,因为它并不声称找不到CoreTestUtil类,而是:

The type com.java11.test.core.util.CoreTestUtil is not accessible   AppTest.java    /java11-app/src/test/java/com/java11/app    line 8  Java Problem
CoreTestUtil cannot be resolved                                     AppTest.java    /java11-app/src/test/java/com/java11/app    line 21 Java Problem

我的假设是,即使该类存在于单独的目录中,也无法从java11-core导出此程序包,并且/或者在java11-app中缺少对该程序包的需求,eclipse会认为访问受到限制。测试罐。

java11-app的模块路径显示它包含java11-core作为模块,并且没有测试代码设置为

enter image description here

我知道我正在使用新发布的功能,并且怀疑尚不支持在Eclipse JPMS项目之间共享测试类。但是,我不确定在哪里可以找到它的更新(Eclipse?M2E插件)。我也不知道有什么变通办法,可以让我在为软件项目采用JPMS时提高工作效率。

对于那些认为不应以这种方式共享测试实用程序的人...

本主题已被描述为最佳实践问题,应通过将测试实用程序重构为单独的模块来解决。我尊重这种观点,但是在尝试遵循该指导原则时,我发现自己被迫违反了其他最佳实践,包括DRY(不要重复自己)以及程序包之间的循环依赖关系。

在开发一个模块时通常会出现一个测试实用程序,该模块既可以帮助对该模块进行有效的测试,又可以依赖于该模块。如果将这些实用程序拉出到单独的模块,则会创建一个周期。此外,其中的一些实用程序在测试依赖于该模块的其他模块时同样有用。如果将这些实用程序复制到依赖项的新测试模块中,则会创建重复的代码。这种推理可能就是为什么最初添加Maven“测试罐”支持的原因。

2 个答案:

答案 0 :(得分:1)

Eclipse 不支持每个项目有多个模块信息:在任何源文件夹(main 或 test)中,您必须只有一个模块信息。

从 Eclipse 的角度来看,您唯一的运气是创建一个新的 Java 项目,引用另一个项目并使用其正确的模块信息/导出:

module mod.a {
  exports com.example.a;
  // com.example.a.Main
}

module mod.a.tests { // (1)
  exports com.example.a.tests;
  // com.example.a.tests.MainUtils calling com.example.a.Main
  requires mod.a;
}

在情况 (1) 中,如果不使用 mod.a.tests,您会遇到问题:Java 永远找不到 com.example.a.Main,可能是因为第二个项目隐藏了第一个项目。

我不是 OSGI 专家,但我认为这就是为什么大多数 Eclipse 插件都有主项目和测试项目的原因之一:org.eclipse.m2e.core 由 {{3} 修补 }

然而,module-info 对“补丁”一无所知:您可以在命令行 (java --patch-module) 上修补模块,但不能在 module-info 本身中进行修补:也许 Eclipse 可以代表您这样做,但它没有。

如您所见,Eclipse 中的两个项目 = 两个 Maven 模块。

在 Maven 的情况下,您当然可以使用相同的构建创建其他人工制品(我确实认为它往往会污染依赖项,因为每次您的辅助人工制品都需要依赖项时,它必须去公共范围)。

这可以使用 maven-compiler-plugin、maven-shade-plugin 和 maven-jar-plugin 来完成:

  • 我认为您不应该依赖 org.eclipse.m2e.core.tests,因为您想通过合并 --patch-moduleclasses 目录来模拟 Java 的 test-classes
  • 由于多个module-info,您不想在Eclipse中导入此项目;或者您必须确保其模块信息仅对 Maven 可见(您可以使用配置文件 + m2e.version 来检测 m2e 并禁用它)。

答案 1 :(得分:0)

我完全同意你的看法。为什么我还可以继承一些src-test功能,为什么只使用某些核心模块中的src-main代码?

但是如何处理范围问题?当我使用“测试”范围时,我松开了与src-main代码的关系。当我不使用测试范围时,我会松开与src-test代码的关系。

我的核心测试代码不会经常更改,因此要使其在Eclipse中正常工作 我将测试罐安装到本地存储库,一切正常。