【问题标题】:Using JUnit 5 with Java 9 without Maven or Gradle在没有 Maven 或 Gradle 的情况下使用 JUnit 5 和 Java 9
【发布时间】:2018-03-23 14:45:08
【问题描述】:

说明:

我想在 Eclipse (Oxygen 4.7.1a) 中使用 JUnit 5 创建一个 JUnit 测试。 此 JUnit 测试应位于名为 Test 的单独 src 文件夹中。但是,由于我是 JUnit 和 Java 9 的新手,我遇到了以下问题。

不想为此使用 Gradle 或 Maven 等构建工具。

问题:

因为我有两个不同的 src 文件夹,一个用于项目 src,一个用于测试用例:

  • 我需要两个 module-info.java 文件吗? (每个 src 文件夹一个)
  • 我的 module-info.java 文件中需要哪些模块才能使 JUnit 5 工作?

【问题讨论】:

  • Maven(构建工具)使用 src/main/java/src/test/java/,因此您可以在 maven 项目中尝试它——遵循新的“最佳实践”。确实是个问题stackoverflow.com/questions/41366582/…
  • 是的,我可以使用 maven,但我更习惯 Gradle。我想在没有 Gradle 的情况下尝试一下,因为我想知道没有这样的构建工具它是如何工作的。
  • guides.gradle.org/building-java-9-modules 不过我能理解; module-info.java 必须在根目录中。并且 junit 通常依赖包可见性来进行类访问。自己还是没有遇到带有junit测试的java 9项目
  • Where should I put unit tests when migrating a Java 8 project to Jigsaw 可能重复? Nicolai 提出的解决方案将使您继续前进。也不确定为什么专门为这个问题标记了 Junit5,但任何类型的单元测试的结构都应该相似。
  • 也将等待@AlanBateman 对上下文进行一些说明...... 我希望及时得到工具、插件、测试运行者的支持......所以定期开发人员不需要关心这个。也许我已经从我的邮件中完全错过了这个线程。

标签: java eclipse junit java-9 junit5


【解决方案1】:

一般来说没有必要模块化你的测试代码(至少我想不出一个正当的理由,也许有人可以给出一个令人满意的反例)。在src 下的主代码中只能有一个module-info.java 文件(毕竟,它甚至不需要模块化主代码)。

由于module-info.java 文件将仅在您的主源目录中,而不是在测试源目录中,因此从逻辑上讲,它不应该依赖于 JUnit 模块。所以现在的问题变成了如何依靠模块(代表被测系统)和JUnit模块来编译和运行JUnit测试类。

为此,您需要使用javacjava 提供的新选项:

所以假设你有以下树:

src
    module-info.java (declares a module called "my.module")
    mypackage
        MyClass.java
test_src
    mypackage
        MyClassTest.java
lib/junit-platform-console-standalone.jar

(注意:专门针对 JUnit 5,您可以使用包含核心 JUnit 引擎并允许在控制台中运行测试的 junit-platform-console-standalone 工件;请参阅the user guide

那么你可以编译如下代码:

cd root_dir
javac -d mods/my.module src/module-info.java src/mypackage/MyClass.java

cd test_src
javac -d test_out --module-path ../mods;../lib/junit-platform-console-standalone.jar \
--add-modules org.junit.platform.console.standalone,my.module --patch-module my.module=. \
--add-reads my.module=org.junit.platform.console.standalone mypackage/MyClass.java

然后你就可以运行编译好的测试类了:

cd test_src/test_out
java --module-path=../../mods;../../lib/junit-platform-console-standalone.jar \
--add-modules my.module,org.junit.platform.console.standalone \
--add-reads my.module=org.junit.platform.console.standalone \
--patch-module my.module=. \
--add-opens my.module/test=org.junit.platform.console.standalone \ 
org.junit.platform.console.ConsoleLauncher test.MyClassTest

笨拙的命令,但这是不使用 Maven 的代价。我建议您在了解模块路径的概念后阅读命令文档中的这些选项。这里需要注意的重要一点是几个选项:

--patch-module my.module=.

这是必需的,因为示例测试代码与模块 my.module 具有相同的包 (mypackage)。没有它,模块系统会报错。

--add-reads my.module=org.junit.platform.console.standalone

这使得 my.module 需要 junit,即使它没有在 module-info.java 中声明。

org.junit.platform.console.standalone自动模块 的名称,并且源自 Jar 清单(与 JUnit 5 一样),否则源自 Jar 文件的名称(例如在JUnit 4)。

另请注意,这是 Maven 在编译和运行单元测试时可能在后台执行的操作(请参阅 this issue 以获取手动执行上述操作的等效插件配置)。

如果出于某种原因,您还想模块化单元测试怎么办?

在这种情况下,由于在上面的示例中单元测试共享同一个包,您可以将它们包含在 my.module 中并向 JUnit 添加要求:

module my.module {
    exports mypackage;
    requires org.junit.platform.console.standalone;
}

如果单元测试位于不同的包中,您还可以将它们拆分为两个模块(两个module-info.java),一个my.module 和一个my.test.module,其中只有后者需要JUnit。

如果您确实在模块中包含测试类,那么在上述命令中,您不需要--add-reads--patch-module

【讨论】:

  • 最后一点,junit 在 jar 清单中有 Automatic-Module-Name 属性(即它不是文件名) - github.com/junit-team/junit5/commit/…
  • (1) 这似乎与 junit5 无关。 (2)它不应该依赖于JUnit模块,为什么?
  • @MichaelEaster 我很糟糕,我正在使用 JUnit 4 尝试这个示例,却忘记了这个问题的上下文。现在更新了,谢谢指正。
  • @nullpointer 我已经更新了关于 JUnit 5 的自动模块的注释。对于依赖关系,如果测试代码和主模块分开,为什么主模块需要 JUnit。关键字“requires”表示模块中的类需要它。
  • @nullpointer 很公平。而且我从来没有说过测试不应该是模块的一部分:)只是我想不出有人会这样做的正当理由,所以没有理由让我的“不需要模块化测试”声明。
【解决方案2】:

测试单独在一个模块中的一个原因是六边形架构。测试模块是一个驱动适配器,可与其他运行业务逻辑的适配器交换。

在我的情况下,我也将使用没有 maven 的 jaba 9 来完成。

这是我关于六边形架构的文章:

https://softwarecampament.wordpress.com/portsadapters/

【讨论】:

    猜你喜欢
    • 2019-12-08
    • 2015-02-20
    • 2021-05-08
    • 1970-01-01
    • 2013-12-14
    • 2018-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多