使用模块化 Java (JavaFX) 项目的 Gradle 构建运行 Eclipse JUnit 测试,该项目还可以使用 Jlink 生成可执行映像
我一直在努力寻找一种干净的方法来处理 gradle 构建的模块化 Java FX 项目(使用 JDK11),它可以生成漂亮的可部署 jlink 映像,同时仍然能够在 Eclipse IDE 中执行 Junit 测试。我有:
- 我的包中的 src/main/java 文件夹中有一个 JavaFX 应用程序,以及必要的 info-module.java 文件。
- JUnit 在 src/test/java 文件夹中的相应包中进行测试,该文件夹显然不包含 info-module.java,因为 Eclipse 不允许每个项目超过 1 个模块。
- gradle.build 文件具有:
plugins {
id 'java-library'
id 'application'
id 'eclipse'
id 'org.openjfx.javafxplugin' version '0.0.12'
id 'org.beryx.jlink' version '2.12.0'
}
dependences {
testImplementation 'junit:junit:4.13'
}
javafx {
version = "16"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
mainClassName = "{my-package}.App"
eclipse {
classpath {
file {
whenMerged {
entries.findAll { it.properties.kind.equals('lib') }.each { it.entryAttributes['module'] = 'true' }
}
}
}
}
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'mini'
}
}
通过此配置,我可以轻松地从 Eclipse 中运行我的 JavaFX 应用程序(使用 gradle -> 应用程序 -> 运行任务),并且可以构建一个可爱的可部署 jlink 映像(使用 jlink 任务)。然而,我无法在我的 IDE 中运行 JUnit 测试,我经常喜欢这样做来测试一些代码和代码想法——也许部分原因是我有点业余,尽管我有相当多的经验。经验。
在互联网上搜索解决方案后,我最终尝试了各种方法,例如将“requires junit”添加到 info-module.java 文件中,摆弄构建路径配置以将 JUnit4 库添加到模块路径中(这显然会消失每个我刷新了gradle),并尝试了JUnit5。我没有发现任何令人满意的事情。当然 Gradle (或者可能是 Eclipse 插件)应该有一个简洁的解决方案吗?这里有一个一刀切的解决方案吗?
I have struggled to find a clean way to work with gradle-built modular Java FX projects (using JDK11), that can produce nice deployable jlink images, whilst still being able to perform Junit tests within the Eclipse IDE. I have:
- A JavaFX app in my package in the src/main/java folder alongside the necessary info-module.java file.
- JUnit tests in a corresponding package in the src/test/java folder, which obviously doesn’t contain an info-module.java because Eclipse doesn’t tolerate >1 module per project.
- A gradle.build file with:
plugins {
id 'java-library'
id 'application'
id 'eclipse'
id 'org.openjfx.javafxplugin' version '0.0.12'
id 'org.beryx.jlink' version '2.12.0'
}
dependences {
testImplementation 'junit:junit:4.13'
}
javafx {
version = "16"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
mainClassName = "{my-package}.App"
eclipse {
classpath {
file {
whenMerged {
entries.findAll { it.properties.kind.equals('lib') }.each { it.entryAttributes['module'] = 'true' }
}
}
}
}
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'mini'
}
}
With this configuration, I can easily run my JavaFX app from within Eclipse (using gradle -> application -> run task) and could build a lovely deployable jlink image (using the jlink task). However, I could not run JUnit tests within my IDE, which I often like to do to test bits of code and code ideas as I go along – perhaps partly because I’m a bit of an amateur, albeit one with a fair bit of experience.
Having scoured the internet for solutions, I’ve ended up trying various things like adding “requires junit” to the info-module.java file, fiddling with build path configurations to add a JUnit4 library to the Module Path (which would obviously disappear every time I refreshed gradle), and trying JUnit5. I’ve found nothing satisfactory at all. Surely Gradle (or perhaps an Eclipse plugin therefor) should have a neat solution? Is there a one-size-fits-all solution here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
经过一番摆弄后,我的解决方案是:
允许 JUnit 测试工作:
a.注释掉 module-info.java 文件中的所有内容 - 这会暂时生成一个非模块化项目。
b.在 build.gradle 中注释掉 eclipse {…} 插件命令 – 这会暂时破坏 eclipse 模块化行为和 jlink 任务。
c.刷新 Gradle。
然后,您可以运行 JUnit 测试,并继续处理您的项目,只要您不需要模块化或 jlink 任务。
恢复镜像构建的模块化和 jlink 任务:
a.取消注释(恢复) module-info.java 文件的内容。
b.在 build.gradle 中取消注释(恢复)eclipse {} 插件命令。
c.刷新 Gradle。
这并不算太痛苦,只要在执行 JUnit 测试时能够在没有模块化的情况下工作即可。不过,请告诉我是否有办法避免所有这些麻烦——也许有 Gradle(或 Eclipse 插件)解决方案?
After fiddling around, my solution is:
To allow JUnit tests to work:
a. Comment out all content within the module-info.java file – this temporarily yields a non-modular project.
b. Comment out the eclipse {…} plugin commands in build.gradle – this temporarily breaks the eclipse modular behaviour and jlink task.
c. Refresh Gradle.
You can then run JUnit tests, and carry on working on your Project, so long as you don’t need modularity or jlink tasks.
To restore modularity and jlink tasks for image building:
a. Uncomment out (restore) the content of the module-info.java file.
b. Uncomment out (restore) the eclipse {} plugin commands in build.gradle.
c. Refresh Gradle.
This isn’t too much of a pain, so long as it’s practical to work without modularity whilst performing the JUnit tests. However, please let me know if there’s a way to avoid all this faffing – perhaps there’s a Gradle (or Eclipse plugin) solution?
这是绝对可以接受的:) 从 IDE 运行测试,尤其是使用更快编译器的 Eclipse,是非常可取的。
切勿将测试依赖项添加到应用程序的模块信息中。我看过一些指南,告诉您如果您的项目是测试项目(您的测试不仅位于不同的源文件夹中,而且完全位于不同的项目中),则添加它们,这可能没问题。
是的,任何基于更改 Eclipse 中的项目配置的解决方案都将是短暂的,因为 Eclipse Gradle 插件(或 Buildship)将在下次同步时接管。
正如您所发现的,只要依赖项仅用于测试,就没有什么区别。
该问题实际上来自JavaFX插件,因为它在
0.1.0
版本之前使用了javamodularity
插件。您可以升级到最新版本,或者尝试通过模块化插件进行配置。此代码
将所有库依赖项放在模块路径上,包括测试依赖项。但是,由于它们未在模块信息中指定,因此您的代码无法访问它们。如果删除此行,则模块路径上不会有任何库,这将使 module-info 中指定的库无法访问。
因此,解决方案是仅将非测试库(位于模块信息中的库)放在模块路径上,并排除测试库。这可以通过查看
"test"
库属性来完成:一些库属性可以在 Eclipse 中查看。请注意将项目与上述更改同步后库之间的差异:

This is absolutely acceptable :) Running tests from the IDE, especially Eclipse, which uses a faster compiler, is very desirable.
Never add test dependencies to the module-info of the application. I've seen some guides that tell you to add them if your project is a tests project (you have your tests not only in a different source folder, but in a different project altogether), which might be fine.
Yes, any solution based on changing the project configuration in Eclipse will be short lived because the Eclipse Gradle plugin (or Buildship) will take over at the next synching.
Doesn't make a difference as long as the dependencies are tests-only, as you've found.
The problem actually comes from the JavaFX plugin because it used the
javamodularity
plugin before version0.1.0
. You can upgrade to the latest version, or try to configure it through the modularity plugin.This code
puts all the library dependencies on the module path, including the test dependencies. However, since they aren't specified in the module-info, they are not accessible to your code. If you remove this line, none of the libraries will be on the module path, which will make those that are specified in the module-info unreachable.
So, the solution is to only put the non-test libraries (those that are in the module-info) on the module path, and exclude the test libraries. This can be done by looking at the
"test"
library attribute:Some of the library attributes can be viewed in Eclipse. Note the differences between the libraries after synching the project with the above change:
