Replies: 7 comments
-
Hi Mark, author of at least 182 unique Java modules published to Maven Central. In the blog "Testing in The Modular World" (2018) I wrote about and created a sample project covering two ways of in-module testing:
As IDEs and Maven (that is the Compiler Plugin and Surefire) didn't support those features back then (at all, nor do they agree today), I also created the "JUnit Platform Maven Plugin". This plugin might mend the cases in your projects in which Surefire breaks by not running on the module path itselfs.
Tests, in general, should be written as close as possible to real code your users would do in their main code. Your tests are your first customers, so to say. From your goal above ("only support using the artifacts I produce on the module path") you are doing right by wanting "to run tests in module-path mode only". That means, customers (your users AND your tests) of your (main) modules must configure the module system correctly. There is no way to work around "all that"; not for your users NOR your tests. You either need to supply and maintain extra module descriptors for testing (as your users do for their modules) or use the super-powers of the command line via extra VM options. @michael-simons wrote about that very topic here: https://info.michael-simons.eu/2021/10/19/testing-in-a-modular-world/ |
Beta Was this translation helpful? Give feedback.
-
Hello!
😅 I think it might actually be significantly more than that by now. For whatever reason, that list is missing quite a few things.
Thanks, I'll take a look at this. That's not going to help tests not running properly in the IDE, though, right?
I feel like I'm doing exactly that. The tests are in a different source root, but that would be true for any users writing code using the artifacts too.
This is where I feel like something is broken somewhere. The main artifacts in all of my projects absolutely do have correct module descriptors (I know because I use lots of my own code in modular projects). The test code only runs against code that is exported in module descriptors; sometimes I'll I'm having to maintain extra module descriptors and use extra VM options despite not doing any kind of magic with my code, or deliberately breaking into the internals of modules. That seems wrong. If we assume that programming with modules is ostensibly the new "standard" way of writing Java code, then I feel like I shouldn't be having to do both of the things above (one correct module descriptor should be enough). Unfortunately, I don't know which of five different systems is at fault ( I'd like to try to get this working properly.
Reading this now. |
Beta Was this translation helpful? Give feedback.
-
Hm, actually, that's one thing I haven't tried: Put all of the tests in the test module in |
Beta Was this translation helpful? Give feedback.
-
I'll also try |
Beta Was this translation helpful? Give feedback.
-
What you describe here, should be the easy and most realistic way of running tests in the modular world. You need to declare an internal module descriptor for testing though, that could follow this structure: open /* to allow deep reflection for test frameworks */ module com.io7m.xyz.tests {
//
// modules under test
//
requires ...;
requires ...;
//
// test framework api
//
requires org.junit.jupiter.api;
requires net.jqwik.api;
} IDEs and build tools should understand that "as-is", at least they did, when I last checked. |
Beta Was this translation helpful? Give feedback.
-
I don't want to speak too soon, but it seems like these were the key things that worked:
This module descriptor has to be duplicated and one placed in I'm going to experiment with using |
Beta Was this translation helpful? Give feedback.
-
I've landed at moving all tests into This works in that Surefire and Failsafe run the tests in module-path mode without needing any VM arguments. It does, however, fail in Intellij IDEA without extra VM arguments. I'm pretty sure the way they're running JUnit is just wrong; it's always on the classpath even if everything else is on the module path. Here's a project with this setup: https://github.com/io7m/idstore |
Beta Was this translation helpful? Give feedback.
-
Hello!
I have rather a lot of projects that use the Java module system. I don't care about testing artifacts in classpath mode as I only support using the artifacts I produce on the module path.
Here's a project I'll use for the sake of this discussion, but I've experienced variations of the same issue on countless other projects:
https://github.com/io7m/cedarbridge
Edit: The project above doesn't have any of the workarounds I mention below; it's a blank slate right now
In order to make JUnit and/or Intellij IDEA's test runner and/or Maven Surefire run the test code such that the module path is used rather than the classpath, I have to add a module descriptor. Because I often have projects that have dozens of individual modules, I have all of the tests in one module. Here's the
cedarbridge
example:https://github.com/io7m/cedarbridge/tree/develop/com.io7m.cedarbridge.tests
If I add a module descriptor in
src/test/java
in thecom.io7m.cedarbridge.tests
module, the Maven compiler plugin complains:I can instead add a module descriptor in
src/main/java
in thecom.io7m.cedarbridge.tests
module.Unfortunately, this then causes Surefire to break when the tests run:
As well as trying to run the tests in the IDE:
I've seen lots of variations on this error on different projects, but the
org.junit.platform.commons
frequently seems to be mentioned.If I add identical module descriptors at both
src/main/java/module-info.java
andsrc/test/java/module-info.java
, this kind of works in that Maven's compiler plugin accepts it, but it does mean maintaining two module descriptors, and it also means that for each real test package insrc/test/java
, I have to have a mirror fake package insrc/main/java
with an empty class in each to allowjavac
to accept the module descriptor.Assuming I actually do all of the above, I can get tests to run if I add the following VM options:
... But this is fairly miserable, as if I click a test to run it in the IDE, it will obviously fail immediately with an
IllegalAccessError
, and I then have to go and add those VM options to the test configuration and run it again.I want to run tests in module-path mode only, and I'd like to know if there's some strategy I can use across ~120 projects that all have largely the same structure without needing extra VM options, multiple descriptors, and all that...
I'm opening the discussion here because I don't know which software is at fault.
Beta Was this translation helpful? Give feedback.
All reactions