junit-team / junit5

✅ The 5th major version of the programmer-friendly testing framework for Java and the JVM
https://junit.org
Other
6.33k stars 1.47k forks source link

Using JUnit 5 in modules production code broken since 5.5.0-RC1 #2147

Closed christianhujer closed 4 years ago

christianhujer commented 4 years ago

When using JUnit in production code, for example, to provide a module with abstract test classes for contract tests, and the production code is using Java 9 modules, and the version of JUnit is JUnit 5.5.0-RC1, then there is a compilation issue.

Expected behavior: It is possible to create a production code module that requires org.junit.jupiter.api for test code reusable by other modules. This was possible until JUnit 5.5.0-M1.

Actual behavior: Since JUnit 5.5.0-RC1, this is no longer possible.

Minimal project structure to reproduce:

src/main/java/module-info.java
src/main/java/com/example/AbstractTest.java
src/test/java/com/example/ImplTest.java
pom.xml

Source code of src/main/java/module-info.java:

module com.example {
    requires org.junit.jupiter.api;
    opens com.example;
}

Source code of src/main/java/com/example/AbstractTest.java:

package com.example;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.fail;

public abstract class AbstractTest {
    @Test
    void test() {
        fail("bar");
    }
}

Source code of src/test/java/com/example/ImplTest.java:

package com.example;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.fail;

abstract class AbstractTest {
    @Test
    void test() {
        fail("bar");
    }
}

Versions of JUnit that work: All versions before and including 5.5.0-M1. Versions of JUnit that don't work: All versions from JUnit 5.5.0-RC1 on, including JUnit 5.6.0-RC1

JDK used: OpenJDK 13.0.1 Build tool used: Maven 3.6.3 with maven-compiler-plugin:3.8.1 and maven-surefire-plugin:3.0.0-M4.

IDE used: IntelliJ IDEA Ultimate 2019.3. Maven and IntelliJ IDEA show the same error message.

Suspected causes:

Error message in IntelliJ IDEA:

Exception in thread "main" java.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x4b9e13df) 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 @0x4b9e13df
    at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:83)
    at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:67)
    at com.intellij.junit5.JUnit5IdeaTestRunner.createListeners(JUnit5IdeaTestRunner.java:46)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:31)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

Process finished with exit code 1

Error message in Maven:

[ERROR] There was an error in the forked processjava.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x27808f31) 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 @0x27808f31
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: There was an error in the forked processjava.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x27808f31) 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 @0x27808f31
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:675)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:285)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:248)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1217)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1063)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:889)
[ERROR]         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR]         at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR]         at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR]         at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
[ERROR]         at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
[ERROR]         at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.base/java.lang.reflect.Method.invoke(Method.java:567)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.base/java.lang.reflect.Method.invoke(Method.java:567)
[ERROR]         at org.apache.maven.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:39)
[ERROR]         at org.apache.maven.wrapper.WrapperExecutor.execute(WrapperExecutor.java:122)
[ERROR]         at org.apache.maven.wrapper.MavenWrapperMain.main(MavenWrapperMain.java:61)
[ERROR] 

Steps to reproduce

Create a project with the above structure and try to run the tests with IntelliJ IDEA or Maven. Alternatively, clone the repository given by the following URL: https://github.com/christianhujer/junit-bug-2147 and play around with it.

Context

sormuras commented 4 years ago

Thanks for the very detailed report, @christianhujer -- much appreciated!

The underlying reason seems to be that both tools (IDEA and Surefire) put the JUnit launcher module on the class- instead of the module-path:

org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x4b9e13df)

I'll take a deeper look into the your MVE and trace the way Surefire manages the paths, and could need some help from @akozlova for the IDEA part. Guess, this issue is related: https://youtrack.jetbrains.com/issue/IDEA-171419

sormuras commented 4 years ago

Here's some background information on the topic: https://sormuras.github.io/blog/2018-09-11-testing-in-the-modular-world#module-infojavatest

tl;dr: You're missing a test module descriptor.

christianhujer commented 4 years ago

I tried creating a test module descriptor. If I put a src/test/java/module-info.java besides the src/main/java/module-info.java, two things happen: • IntelliJ IDEA reports an issue "'module-info.java' already exists in module", no matter whether the name of the module is the same (like module com.example) or different (like module com.example.test). • If the test module name is different, it will no longer be able to find the production code during test code compilation because they are in the same package (which should be possible for unit testing), because packages with the same name in different modules do not see each other (as far as I understand) • If the test module name is the same, the error is still the same.

The important aspect is not just using modules, but having a JUnit dependency in src/main/java because of reusable test code for other modules. Without that, everything works fine.

sormuras commented 4 years ago

Downgraded Surefire to 3.0.0-M3 (and 2.22.2) and the error vanished ... BUT no tests are found/executed:

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

IntelliJ IDEA reports an issue "'module-info.java' already exists in module", [...]

~Try the module-info.test configuration file. This bypasses the name clash.~ Never mind. IDEA 2020.1 will introduce support for this feature, soon. https://youtrack.jetbrains.com/issue/IDEA-222831

The important aspect is not just using modules, but having a JUnit dependency in src/main/java because of reusable test code for other modules. Without that, everything works fine.

That shouldn't break things. See https://github.com/sormuras/mainrunner or https://github.com/junit-pioneer/junit-pioneer or many (all?) of those projects here https://github.com/junit-team/junit5/wiki/Third-party-Extensions -- they all depend on JUnit in their production/main code.

Having said that, it appears that your main module is not configured correctly, in terms of re-useability. It doesn't export any package, does it?

https://github.com/christianhujer/junit-bug-2147/blob/c75f1a9841a2b5d29ee6ffe5a0bf933bcd7d7377/src/main/java/module-info.java#L1-L4

The easiest (and best way) is to a) export at least one package from your main module and b) have a differently named test module that reads your main module. Black box or inter-module testing. Let your test be your first customer.

If you want to do white box (intra-module) testing, you have to guide most build tool manually, how to do it right. Or use pro or bach. 😉

sormuras commented 4 years ago

Another solution: let https://github.com/sormuras/junit-platform-maven-plugin replace Surefire.

This Maven plugin knows how to run intra-module tests correctly. See this output:

[ERROR] Thanks for using JUnit! Support its development at https://junit.org/sponsoring
[ERROR]
[ERROR] .
[ERROR] '-- JUnit Jupiter [OK]
[ERROR]   '-- ImplTest [OK]
[ERROR]     +-- test() [X] bar
[ERROR]     '-- test2() [X] foo

CAVEAT: this plugin is still "work in progress".

christianhujer commented 4 years ago

The main module in the sample code is not configured to export anything because I felt that's irrelevant to reproduce the error. The sample case is distilled from a project where the corresponding module-info.java looks like this:

module com.nelkinda.docio.reader.test {
    requires static java.xml;
    requires static org.jetbrains.annotations;
    requires org.junit.jupiter.api;
    requires org.junit.platform.commons;
    requires transitive com.nelkinda.docio.reader;
    requires org.xmlunit;
    requires lombok;

    provides com.nelkinda.docio.reader.DocumentReader with com.nelkinda.docio.reader.test.DummyDocumentReader;

    exports com.nelkinda.docio.reader.test;
    opens com.nelkinda.docio.reader.test;
}

The test-module already is a separate maven module in my actual project, for a different reason: The test is supposed to provide a service implementation, for which it needs to be a separate module (unless somebody wants to go back to META-INF/services/ which was a workaround I'm currently trying to get rid of in this project).

For JUnit, you're using Gradle to build, isn't it? AFAIK, Gradle has the best Java modules so far.

sormuras commented 4 years ago

For JUnit, you're using Gradle to build, isn't it?

Yes.

AFAIK, Gradle has the best Java modules so far.

No, not at all.

image

https://guides.gradle.org/building-java-9-modules needs the help of community plugins: like https://github.com/java9-modularity/gradle-modules-plugin

Pro and Bach.java are in lead of first-class support of Java modules at the moment. Maven next, Gradle didn't even start. That's how (partly) we at JUnit 5 monkey patch Gradle to work with modules: https://github.com/junit-team/junit5/blob/8dfcee3207d982db1a7bb2a11b44cd4f4a7a1116/buildSrc/src/main/kotlin/java-library-conventions.gradle.kts#L212-L269 Or take a look here: https://github.com/openjdk/skara/blob/master/buildSrc/module/src/main/java/org/openjdk/skara/gradle/module/ModulePlugin.java

Most pre Java 9 build tools lack Java module support due to their ideas of "collection of packages" in their project models. (...) But that's totally off-topic.

On-topic: the changes in JUnit 5's module descriptors made in 1/5.6.0-RC1 are fine, afaict. All our internal tests and my sample projects are building correctly. Somehow those changes make Surefire and IDEA resort putting the JUnit Launcher module on the class-path, though. Edit: I upgraded the "junit5-modular-world" sample project as well: https://github.com/junit-team/junit5-samples/compare/sormuras-junit-5.6 -- which uses javac/java CLI to compile and run tests. All is fine here, too.

sormuras commented 4 years ago

Find junit-platform-launcher-1.6.0-RC1.jar in line 9 of the Surefire log. Along with maaany other modules, that should reside in line 7, i.e. the --module-path.

@tibor17 ... where does Surefire decide which JAR goes either on the class- or module-path? @rfscholte ... what does the maven-compiler-plugin try to tell us with the following jpms.args found in target/test-classes/META-INF?

--patch-module
com.example=_
--add-reads
com.example=ALL-UNNAMED
sormuras commented 4 years ago

Same goes for the command line generated by IDEA to run the test plan:

D:\dev\jdk\jdk-11.0.5+10\bin\java.exe
-ea
-Didea.test.cyclic.buffer.size=1048576
-javaagent:C:\Java\tool\JetBrains\IntelliJ-IDEA-CE-193\lib\idea_rt.jar=54246:C:\Java\tool\JetBrains\IntelliJ-IDEA-CE-193\bin
--patch-module com.example=D:/dev/misc/junit-bug-2147/target/test-classes
--add-reads com.example=ALL-UNNAMED
--add-opens com.example/com.example=ALL-UNNAMED
--add-modules com.example
-Dfile.encoding=UTF-8
-classpath
  C:\Java\tool\JetBrains\IntelliJ-IDEA-CE-193\lib\idea_rt.jar;
  C:\Java\tool\JetBrains\IntelliJ-IDEA-CE-193\plugins\junit\lib\junit5-rt.jar;
  C:\Java\tool\JetBrains\IntelliJ-IDEA-CE-193\plugins\junit\lib\junit-rt.jar;
  D:\dev\misc\junit-bug-2147\target\test-classes;
  C:\Users\Sor\.m2\repository\org\junit\platform\junit-platform-launcher\1.6.0-RC1\junit-platform-launcher-1.6.0-RC1.jar;
  C:\Users\Sor\.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;
  C:\Users\Sor\.m2\repository\org\junit\platform\junit-platform-engine\1.6.0-RC1\junit-platform-engine-1.6.0-RC1.jar;
  C:\Users\Sor\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;
  C:\Users\Sor\.m2\repository\org\junit\platform\junit-platform-commons\1.6.0-RC1\junit-platform-commons-1.6.0-RC1.jar;
  C:\Users\Sor\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.6.0-RC1\junit-jupiter-engine-5.6.0-RC1.jar;
  C:\Users\Sor\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.6.0-RC1\junit-jupiter-api-5.6.0-RC1.jar
-p C:\Users\Sor\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.6.0-RC1\junit-jupiter-api-5.6.0-RC1.jar;
  D:\dev\misc\junit-bug-2147\target\classes;
  C:\Users\Sor\.m2\repository\org\junit\platform\junit-platform-commons\1.6.0-RC1\junit-platform-commons-1.6.0-RC1.jar;
  C:\Users\Sor\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;
  C:\Users\Sor\.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar
com.intellij.rt.junit.JUnitStarter
-ideVersion5
-junit5
com.example.ImplTest

IDEA even puts same JAR files on the class- AND the module-path. See -p option above.

marcphilipp commented 4 years ago

@christianhujer Thanks a lot for bringing this to our attention!

5.5.0-RC1 was the first version that included module descriptors. Thus, it's handled differently by plexus-java which Surefire uses to determine which jars to put on the module path.

I found a workaround and submitted a PR to your sample project repo: https://github.com/christianhujer/junit-bug-2147/pull/2

In addition, I submitted a PR to Surefire to remove the usage of our internal API: https://github.com/apache/maven-surefire/pull/263

I'm not sure the workaround feasible for your actual project but I'm afraid it's the best we can do. The module descriptors included in our jars are correct. Please raise issues with Surefire and/or IDEA to make them adapt their logic.

verhas commented 3 years ago

I am using 5.7.0 at the moment and I had to add to exports to the argLine of surefire:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
        <argLine>
            --add-opens yamaledt/javax0.yamaledt=org.junit.platform.commons
            --add-exports org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED
            --add-exports org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED
        </argLine>
    </configuration>
</plugin>
marcphilipp commented 3 years ago

@verhas Which version of JUnit Platform are you using?

verhas commented 3 years ago

I think the answer to your question is in my comment: 5.7.0 Possibly, I do not understand what version you are asking about. Anyway, you can see the whole project with all the history at

https://github.com/verhas/yamaledt

marcphilipp commented 3 years ago

On second thought, both util and logging are internal packages and deliberately not exported. What's your use case for accessing them?

verhas commented 3 years ago

I myself nothing. But without those two lines running Maven I get the following error:

[ERROR] Please refer to /Users/verhasp/github/yamaledtest/target/surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] There was an error in the forked process
[ERROR] java.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x2f8f5f62) 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 @0x2f8f5f62
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: There was an error in the forked process
[ERROR] java.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x2f8f5f62) 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 @0x2f8f5f62
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:733)
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:305)
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:265)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1314)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1159)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:932)
[ERROR]     at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR]     at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR]     at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR]     at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
[ERROR]     at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
[ERROR]     at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
[ERROR]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]     at java.base/java.lang.reflect.Method.invoke(Method.java:564)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)

My guess is that this is a bug in the Surefire bug and these two lines are more a workaround than a fix.

sormuras commented 3 years ago

Surefire/Failsafe/Plexus (or another player) builds up a wrong mix of class-path and module-path here, methinks.

Let's insert some line breaks:

[ERROR] java.lang.IllegalAccessError: 

class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x2f8f5f62)

cannot access 

class org.junit.platform.commons.util.Preconditions (in module org.junit.platform.commons)

because module org.junit.platform.commons does not export 

(package) org.junit.platform.commons.util to unnamed module @0x2f8f5f62

From that I read:

Could you please run Maven with -X to verify that Surefire generates such a class-path/module-path mix?

sormuras commented 3 years ago

PS: I scanned the source files of Surefire for usages of not-exported packages and couldn't fine one. Except for a single hit within a test case here:

https://github.com/apache/maven-surefire/blob/e9e5193feee08230e934f5f0fbdc8f69eda0fb0c/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java#L463-L466

Tibor17 commented 3 years ago

Run the build with debug logs. You don't have to analyse the code if you want to see the JPMS attributes. Simply run mvn -X test.

university666 commented 9 months ago

我也遇到了这个问题,但通过以下方法暂时避免了报错: 1,module-info.Java中使用 requires static junit; //而不是使用 requires org.junit.jupiter.api;

2,测试代码中,使用 import org.junit.Test; //而不是使用 import org.junit.jupiter.api.Test;

通过以上两步,可以有效避免以下错误: java.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x76f2b07d) 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 @0x76f2b07d

university666 commented 9 months ago

相关module-info.Java如下所示: module com.example.demo { requires java.base; requires spring.boot; requires spring.boot.autoconfigure; requires spring.boot.test; requires spring.context; requires org.apache.tomcat.embed.core; // requires org.junit.jupiter.api; requires spring.beans; requires static junit; }

sbrannen commented 9 months ago

@university666,

Your proposed "fix" is to switch from JUnit Jupiter (JUnit 5) to JUnit 4, which is arguably not an actual fix.

Furthermore, this issue was closed 4 years ago, so please refrain from posting on old closed issues.

If you believe you have discovered an issue with a recent of JUnit 5, please create a new issue to discuss that.

In addition, please use English when creating issues and comments. If you need assistance with English, please ask a friend or colleague to help you or use a translation tool such as DeepL or Google Translate.

Thanks

university666 commented 8 months ago

@sbrannen Thank you for your suggestion!

I have encountered such a problem: Firstly, i use the spring boot initializr, create a project,https://start.spring.io/; Project--->maven Language--->java Spring Boot--->3.2.1 Project Metadatat--->default Packaging--->jar Java--->21 Dependencies--->SpringWeb Generate and extract to working directory,import it in Eclipse IDE.It will generate a test class by default, in src/test/java/DemoApplicationTests.java, like this: `package com.example.demo;

import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest class DemoApplicationTests {

@Test
void contextLoads() {
    System.out.println("hello");
}

} ` From the import statement, we are confident that Junit5 is being used.

Secondly,right click Run as--->Junit Test, Springboot started and everything went smoothly: WARNING: A Java agent has been loaded dynamically (D:\Environments\Maven_jar\net\bytebuddy\byte-buddy-agent\1.14.10\byte-buddy-agent-1.14.10.jar) WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information WARNING: Dynamic loading of agents will be disallowed by default in a future release OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended hello

Thirdly, we will create a module info. jar that contains the following code: `module com.example.demo { requires java.base; requires spring.boot; requires spring.boot.autoconfigure; requires spring.boot.test; requires spring.context; requires org.apache.tomcat.embed.core; requires org.junit.jupiter.api; requires spring.beans;

exports com.example.demo;

}`

"Requires spring. boot. test;" and "requires org.JUnit.JUPITER. API;"; Prompt us to "Move classpath entry 'Maven Dependencies' to modulepath" We followed the prompts, but there was still a prompt: "spring.boot.test cannot be resolved to a module". We selected "fix project setup" and added archive 'junit Jupiter apis' 5.10.1. jar 'and to' spring boot test 3.2.1. jar 'buildpath, Wait until all prompts disappear, run the test again and encounter the following error message:

java.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x27a5f880) 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 @0x27a5f880 at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:128) at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:112) at org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.<init>(JUnit5TestLoader.java:37) at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502) at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128) at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:304) at java.base/java.lang.Class.newInstance(Class.java:725) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createRawTestLoader(RemoteTestRunner.java:371) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:366) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:310) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:225) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

I have searched a lot of information online, and I don't know why I used "module info. java", which resulted in an error message. I'm not sure if it's an issue with Eclipse or Junit5.

If you know the reason, please kindly help to answer it. The above is from machine translation. If it sounds awkward, please understand.

Thanks

sormuras commented 8 months ago

The IllegalAccessError stems from using --class-path and --module-path at the same time.

Move/mount all, at least all JUnit JAR files, onto the same search path.

university666 commented 8 months ago

@sormuras Thank you for your answer! But I have already moved all dependencies to modulePath in buildPath, and classPath is empty. I don't know why this problem still occurs. Perhaps it's an issue with Eclipse, so I can import this project into IDEA and use it without any problem. And the dependency of the module info. jar in idea is much less than that in eclipse. The above is from machine translation. If it feels a bit awkward to read, please understand.

raphaelbalbanez commented 5 months ago

Boa noite, estou tentando executar o JUnit e está apresentando o seguinte erro... é um projeto simples com poucas classes quem quiser da uma olhada está no meu repositório.

java.lang.IllegalAccessError: class org.junit.platform.launcher.core.ServiceLoaderRegistry (in unnamed module @0x50134894) cannot access class org.junit.platform.commons.logging.LoggerFactory (in module org.junit.platform.commons) because module org.junit.platform.commons does not export org.junit.platform.commons.logging to unnamed module @0x50134894 at org.junit.platform.launcher.core.ServiceLoaderRegistry.(ServiceLoaderRegistry.java:27) at org.junit.platform.launcher.core.LauncherFactory.(LauncherFactory.java:66) at org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.(JUnit5TestLoader.java:37) at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128) at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:341) at java.base/java.lang.Class.newInstance(Class.java:677) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createRawTestLoader(RemoteTestRunner.java:371) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:366) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:310) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:225) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

sormuras commented 5 months ago

Similar issue as above: the "internal RemoteTestRunner of Eclipse" puts some JUnit modules on the module path

Furthermore, this issue was closed 4 years ago, so please refrain from posting on old closed issues.

If you believe you have discovered an issue with a recent of JUnit 5, please create a new issue to discuss that.

In addition, please use English when creating issues and comments. If you need assistance with English, please ask a friend or colleague to help you or use a translation tool such as DeepL or Google Translate.

Thanks