Hi all, Apologies for the long email, but whitebox testing is a complex topic. I know not everyone agrees with whitebox testing, but it is a major factor in how many projects are written, and IMO Maven should fully and easily support it.
A "whitebox mode" test has two module-info.java files, both with the same module name. The goal is to support unit testing with full access to the internals of the module as in the "good ole days" while ensuring that the test occurs on the module-path (test failures can occur on the module-path which do not occur on the class-path, and vice versa): root - pom.xml - src/main/java -- module-info.java -- mypackage --- Main,java - src/main/resources -- mypackage --- main.txt - src/test/java -- module-info.java -- mypackage --- Test,java The main module-info would be something like: module mymodule { exports mypackage; } The test module-info would be something like: open module mymodule { // duplicate contents of main module-info exports mypackage; // any additional test dependencies/services requires transitive org.junit.jupiter; } The good news is that a setup like this mostly works today in Maven (tested with v3.9.9 and Java 21). However there are three key issues: The way Maven currently operates is: 1) In `testCompile`, the test source code is compiled using: --module-path target/test-classes:target/classes --patch-module mymodule=src/main/java 2) In `surefire`, the tests are run with: --module-path target/test-classes:target/classes:<< dependencies >> --class-path << surefire jar files >> What actually happens is (I think) very surprising. TestCompile compiles BOTH the main and test source code into `target/test-classes`: target/classes contains - module-info.class (from src/main/java) - mypackage/Main.class - mypackage/main.txt target/test-classes contains - module-info.class (from src/test/java) - mypackage/Main.class - mypackage/Test.class This results in three issues: A) The code in `src/main/java` is compiled twice, which is unnecessary, surprising and slows things down B) There is no need to refer to `target/classes` on the module-path, as it is not used in TestCompile or Surefire. C) Any resource files (src/main/resources) are UNAVAILABLE to Surefire, which results in the tests failing, eg. `Main.class.getResourceAsStream("main.txt")` will return null. This is because Surefire sees the code in target/test-classes as the complete definition of the module, and as shown above `main.txt` is not present in `target/test-classes`. ----- Option 1: Do nothing. End users can fix the resource file issue by adding this to the pom.xml: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <argLine>--patch-module mymodule=src/main/resources;</argLine> </configuration> </plugin> This causes Surefire to pickup the resource folder and patch it into the module. Option 2: Automate the patch-module described above. When Surefire runs in "whitebox mode", the --patch-module outlined above should be automatically generated and added to the command line. Care will be needed not to clash with any patch-module the user adds manually. This fixes issue C. Option 3: Properly address the issue. maven-compiler-plugin already recognises that there are two module-info.java files and checks the names. If they are different it sets up "blackbox mode". IMO, maven-compiler-plugin needs an official "whitebox mode". The correct approach, as far as I can determine, is for TestCompile to do the following: --module-path target/test-classes --patch-module mymodule=target/classes This avoids the main source code being compiled twice - it is patched in instead. The same change needs to be applied to Surefire --module-path target/test-classes:<< dependencies >> --patch-module mymodule=target/classes This fixes issues A , B and C. (The resource files in target/classes are patched in alongside the .class files). Note that the java command line generates a warning about duplicate module-info.class files, but that is expected in this case,and can be ignored. --- So, what do people think? Is there appetite to raise an issue to get option 2 or 3 done? thanks for reading this far Stephen Colebourne PS. IDEs don't like the two module-info.java files of whitebox testing, but that's OK - Maven isn't beholden to IDEs. It also turns out there is an easy workaround for IDEs (which I can describe in another email, as this one is too long) PPS. I know about the suggested module-info.test file - lets not get into that discussion here --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@maven.apache.org For additional commands, e-mail: users-h...@maven.apache.org