So I looked a bit more into that bug and why it crashes the way it crashes.
I also added this as a comment to the ticket but given the silence on most
tickets, I'd like to push for some discussion here on the mailing list.


I have two modules, core and testing (these are defined modules, they have
a module descriptor)

"core" is just a regular build, it uses junit5 as its test framework.

surefire creates a classpath with all the surefire deps (surefire-api,
surefire-extensions, surefire-junit-platform, surefire-logging-api,
surefire-shared-utils) and the junit deps (junit-jupiter-api,
junit-jupiter-engine, junit-jupiter-params, junit-platform-commons,
junit-platform-engine, junit-platform-launcher). The module path only gets
the actual module dependencies of module A

All works well in that case.

Now the "testing" module declares org.junit.jupiter.api as a dependency and
has requires org.junit.jupiter.api in its module descriptor (transitive or
not transitive does not matter) because there is code that implements some
of those APIs.

surefire now creates a classpath with the same surefire deps and only a
subset of junit deps. The missing deps (junit-jupiter-api and
junit-platform-commons) are pulled onto the module path.

This explains the error message:

*java.lang.IllegalAccessError: class
org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder (in
unnamed module @0x6392827e) cannot access class
org.junit.platform.commons.util.Preconditions (in module
org.junit.platform.commons) because module org.junit.platform.commons does
not export org.junit.platform.commons.util to unnamed module @0x6392827e*

The launcher (in junit-platform-launcher) lives on the classpath and is
therefore in the unnamed module. But the launcher requires the
org.junit.platform.commons module from the junit-platform-commons jar,
which is on the module path. And the junit-platform-commons module has the
following clause in its module descriptor:

exports org.junit.platform.commons.util to
    [...]
    org.junit.platform.launcher,
    [...];

and it does not export the package to the unnamed module. And now JVM fails
with the error above.

I can not see any good solution:

- The current solution does not work (see above)
- The junit-jupiter-api jar which contains org.junit.jupiter.api can not go
on the class path because now the main artifact which requires it can not
find it (the classes would be in the unnamed module and the main module
requests org.junit.jupiter.api)
- It can not be patched into the main module because now
the org.junit.jupiter.api module would be invisible to everything else on
the module path (packages can't exist twice)
- It can only stay on the module path if everything that depends on it gets
pulled there as well. This requires a "bottom up" resolution of all modules
that depend on this (in this case org.junit.jupiter.api) and may interfere
with the ability of the surefire launcher to launch code.
- We could fall back to "legacy" mode where everything is on the classpath
and the module path is ignored. This is problematic as tests may pass and
code later fails because of not matching entries in the module descriptor

Thoughts? This seems to be a blocker for projects that want to use JPMS and
implement test code.

-h

Reply via email to