Closed dbalek closed 2 months ago
It's probably caused by some API changes between JUnit 5.9 & 5.10.
I was trying to update the JDT Test to the latest version but unfortunately it will cause the legacy JUnit tests fails. See: https://github.com/microsoft/vscode-java-test/pull/1608
Why is the IDE embedding a version of JUnit that is incompatible with the version used by the project? This seems poorly thought out as these versions will unlikely align
I need to correct my statement before; the problem is not caused by the embedded JUnit libraries.
The test runner will use the project's JUnit dependencies if they are available. Only when the required dependencies are not declared by the project, the test runner will use the embedded ones.
The problem is caused due to some concept mismatch between the JDT project and the Gradle project.
If I run ./gradlew dependencies
from the sample project, I can see both JUnit 5.9.3
and 5.10.0
are declared in different source sets. That is fine for a Gradle project, because in Gradle projects, each source set can have its own classpath.
Unfortunately, the concept of source set does not exist for a JDT project. One JDT project can only have one .classpath
file which persists the classpath of the whole project. So, when importing a Gradle project to a JDT project, a 'workaround' is done to mitigate this kind of mismatch, that is to merge the classpath from all Gradle source sets into one.
For the sample project, the problem happens after merging. Both 5.9.3
and 5.10.0
are used in the classpath. Then who comes first wins -- the mismatch happens!
From the JDT side, there are two options to solve the issue:
Maybe, from Micronaut side, a workaround is to align the JUnit version for all the sourceset. But I admit that, to entirely solve the issue, something needs to be done at JDT side.
so if you run:
/gradlew dependencies --configuration runtimeClasspath | grep junit
| +--- org.junit:junit-bom:5.9.3
| | +--- org.junit:junit-bom:5.9.3
The only thing that is there is a BOM which should not be in the classpath. if you run:
./gradlew dependencies --configuration testRuntimeClasspath | grep junit
| +--- org.junit:junit-bom:5.9.3 -> 5.10.0
| | +--- org.junit.jupiter:junit-jupiter:5.10.0 (c)
| | +--- org.junit.jupiter:junit-jupiter-api:5.10.0 (c)
| | +--- org.junit.jupiter:junit-jupiter-engine:5.10.0 (c)
| | +--- org.junit.platform:junit-platform-console:1.10.0 (c)
| | +--- org.junit.platform:junit-platform-launcher:1.10.0 (c)
| | +--- org.junit.jupiter:junit-jupiter-params:5.10.0 (c)
| | +--- org.junit.platform:junit-platform-commons:1.10.0 (c)
| | +--- org.junit.platform:junit-platform-engine:1.10.0 (c)
| | \--- org.junit.platform:junit-platform-reporting:1.10.0 (c)
| | +--- org.junit:junit-bom:5.9.3 -> 5.10.0 (*)
| | +--- io.micronaut.test:micronaut-test-junit5:4.0.2 (c)
+--- org.junit.jupiter:junit-jupiter-api -> 5.10.0
| +--- org.junit:junit-bom:5.10.0 (*)
| \--- org.junit.platform:junit-platform-commons:1.10.0
| \--- org.junit:junit-bom:5.10.0 (*)
+--- io.micronaut.test:micronaut-test-junit5 -> 4.0.2
| +--- org.junit.jupiter:junit-jupiter-api:5.9.3 -> 5.10.0 (*)
+--- org.graalvm.buildtools:junit-platform-native:0.9.25
| +--- org.junit:junit-bom:5.10.0 (*)
| +--- org.junit.platform:junit-platform-console:1.9.3 -> 1.10.0
| | +--- org.junit:junit-bom:5.10.0 (*)
| | \--- org.junit.platform:junit-platform-reporting:1.10.0
| | +--- org.junit:junit-bom:5.10.0 (*)
| | \--- org.junit.platform:junit-platform-launcher:1.10.0
| | +--- org.junit:junit-bom:5.10.0 (*)
| | \--- org.junit.platform:junit-platform-engine:1.10.0
| | +--- org.junit:junit-bom:5.10.0 (*)
| | \--- org.junit.platform:junit-platform-commons:1.10.0 (*)
| +--- org.junit.platform:junit-platform-launcher:1.9.3 -> 1.10.0 (*)
| \--- org.junit.jupiter:junit-jupiter -> 5.10.0
| +--- org.junit:junit-bom:5.10.0 (*)
| +--- org.junit.jupiter:junit-jupiter-api:5.10.0 (*)
| +--- org.junit.jupiter:junit-jupiter-params:5.10.0
| | +--- org.junit:junit-bom:5.10.0 (*)
| | \--- org.junit.jupiter:junit-jupiter-api:5.10.0 (*)
| \--- org.junit.jupiter:junit-jupiter-engine:5.10.0
| +--- org.junit:junit-bom:5.10.0 (*)
| +--- org.junit.platform:junit-platform-engine:1.10.0 (*)
| \--- org.junit.jupiter:junit-jupiter-api:5.10.0 (*)
\--- org.junit.jupiter:junit-jupiter-engine -> 5.10.0 (*)
All the JUnit dependencies are promoted from 5.9.3 to 5.10.0 (the correct version). So it seems to me that the classpath produced by the JDT tooling is simply incorrect and the collection algorithm for dependencies incorrect and inconsistent with the behaviour of Gradle which is a massive problem
The problem happens due to org.junit.platform:junit-platform-commons
+--- io.micronaut.platform:micronaut-platform:4.1.2
| +--- org.junit:junit-bom:5.9.3
| | +--- org.junit.jupiter:junit-jupiter-api:5.9.3 (c)
| | \--- org.junit.platform:junit-platform-commons:1.9.3 (c)
Caused by: java.lang.NoSuchMethodError: 'java.util.stream.Stream org.junit.platform.commons.support.ReflectionSupport.streamNestedClasses(java.lang.Class, java.util.function.Predicate)'
if you look at the graph the correct version junit-platform-commons
in my aforementioned comment is selected by the Gradle dependency configuration hence why it works in Gradle and not in VSCode
The bug appears to be that VScode is erroneously including the dependencies of io.micronaut.platform:micronaut-platform:4.1.2 which is a BOM not a dependency.
The classpath computation is clearly broken here.
We can of course "fix" this on the Micronaut side but the bug will still be there waiting to be hit again
A workaround is to add testImplementation("org.junit.platform:junit-platform-commons:1.10.0")
to the Gradle build but this is a workaround and should never be necessary in the first place since VSCode/JDT is computing an erroneous classpath that differs from the one Gradle computes
Seems this is related to https://github.com/microsoft/vscode-java-test/issues/1020 which again sounds like the classpath computation for Gradle is simply incorrect
I want to clarify that I'm not denying that current JDT cannot handle the problem perfectly. As I already said above:
But I admit that, to entirely solve the issue, something needs to be done at JDT side.
All the above comment I left is the analysis that I found why the classpath is wrong in JDT, and provide a possible workaround if it's still blocking before the issue is solved from JDT side. Please don't get me wrong.
I have the same problem with a Spring Boot gradle project in Eclipse. Using org.junit:junit-bom:5.10.1
that lead to org.junit.platform:junit-platform-commons:1.10.1
testImplementation("org.junit.platform:junit-platform-commons:1.10.0")
fixed the problem, but I am puzzled why...
Dup with https://github.com/microsoft/vscode-java-test/issues/1045#issuecomment-676911725.
There will be some update around this.
See: https://github.com/microsoft/build-server-for-gradle/issues/119
The Gradle Test Delegation (both run and debug) has supported now.
To use this feature, you need to install the latest Test Runner for Java and Gradle for Java extension.
To delegate the tests to Gradle, you can set the default testing profile in Testing explorer:
If you do not want to change the default testing profile, you can trigger an one-time execution via:
Generate a sample Micronaut project using Micronaut Launch service with
Micronaut 4.1.1
,Java 17
,Gradle
, andJUnit
selected. Open generated project in VSCode with the Extension Pack for Java installed. Try to run project tests either viaTest Explorer
or by clickingRun Test
icons in source editor gutter. No test gets executed and the following error appear in the console: