119

I have a simple app using Spring Boot and Junit 5:

  • When using Spring Boot 2.1 (e.g, 2.1.8 or 2.1.12), my unit tests run smoothly

  • When using Spring Boot 2.2 (e.g., 2.2.2.RELEASE or 2.3.2.RELEASE) my unit tests fail with error message

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test) on project XXX: There are test failures. [ERROR] [ERROR] Please refer to D:\Projets\workspace\XXX\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] TestEngine with ID 'junit-vintage' failed to discover tests [ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: There was an error in the forked process [ERROR] TestEngine with ID 'junit-vintage' failed to discover tests [ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:656) 

I am using Maven 3.6.1, JDK 1.8, JUnit 5.6.0 and JUnit platform 1.6.0. I exclude the dependency on junit:junit from spring-boot-starter-test, so that I have no JUnit 4 artifacts left in the dependency tree. Note that both Spring Boot 2.2 and 2.3 use maven-surefire-plugin 2.22.2, so my problem does not originate from any regression of the maven-surefire-plugin.

Should I stick to Spring Boot 2.1 in order to have my unit test working?

2
  • For it means mvn, is using the wrong JDK 11, instead of 15 Commented Jun 29, 2021 at 10:56
  • I have misconfiguration in pom.xml file and This answer helped me Commented Nov 19, 2022 at 15:46

23 Answers 23

132

I found the error. The dependency on spring-boot-starter-test brings a dependency on junit-vintage-engine. The latter must be excluded:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> 
Sign up to request clarification or add additional context in comments.

2 Comments

this dependency is really troublesome. I already had these exclusions. <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> <exclusion> <groupId>com.vaadin.external.google</groupId> <artifactId>android-json</artifactId> </exclusion>
This is the only correct solution. The other solutions that suggest that you add a dependency with a specific version might work but the issue is that you get a transitive dependency with a wrong version. Therefore you must exclude it as mentioned here. If you want to understand the issue better, it may be also very useful to run maven in debug mode (mvn test -X) or print dependency tree (mvn dependency:tree). I used a different dependency and I had to exclude junit-jupiter-api, so try to check the dependency tree.
52

Adding the following dependency explicitly to upgrade junit-vintage-engine resolves the issue:

<dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>5.7.0</version> </dependency> 

2 Comments

Invalidating Intellij cache after adding the above dependency resolved my issue
This helped in a project that is not spring-boot based but is built with Maven and uses Junit 5 tests :)
24

The best option is to run the Maven test with debugging enabled:

e.g. mvn clean test -X. It will show the exact failure reason.

In my case, I was attempting to run some Spock tests, but the necessary Groovy XML dependency was not found (as evident from the stack trace provided below). I resolved this issue by explicitly adding the Groovy dependency to my project.

TestEngine with ID 'spock' failed to discover tests org.junit.platform.commons.JUnitException: TestEngine with ID 'spock' failed to discover tests at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:111) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:85) at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:92) at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:67) at org.apache.maven.surefire.junitplatform.TestPlanScannerFilter.accept(TestPlanScannerFilter.java:56) at org.apache.maven.surefire.api.util.DefaultScanResult.applyFilter(DefaultScanResult.java:102) at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.scanClasspath(JUnitPlatformProvider.java:147) at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:128) at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:428) at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:562) at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:548) Caused by: java.lang.NoClassDefFoundError: groovy/xml/MarkupBuilder at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ... 

1 Comment

I strongly agree with you! In my case, I also checked the dump file from surefire and there I found a notorious error about NoClassDefFoundError for another class. You really helped me.
15

In my case, the problem was solved by invalidating ide (IntelliJ) cache.

File > Invalidate Cache > Invalidate and Restart

enter image description here

Comments

10

In my case (GRADLE and Spring Boot 2.x.x), adding exclusion for vintage worked

configurations { all { exclude(group = "junit", module = "junit") exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } } 

Comments

9

I had this issue as well. I've tried different solutions mentioned above, but nothing worked. The one that did work was the simple and ridiculous restart of Intellij.

Comments

9

For the reported error in the question or the below error, both relate to the same problem.

java.lang.NoClassDefFoundError: junit/runner/Version 

This error occurs if the project excludes or not include JUnit 4 when it depends on spring-boot-starter-test. The spring-boot-starter-test depends on junit-vintage-engine by default. To resolve this issue either we have to exclude junit-vintage-engine Or should not depend on spring-boot-starter-test.

testImplementation('org.springframework.boot:spring-boot-starter-test:2.2.2.RELEASE') { exclude group: 'junit' exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } testImplementation('org.junit.jupiter:junit-jupiter-api:5.5.2') testImplementation('org.junit.jupiter:junit-jupiter-engine:5.5.2') testImplementation('org.junit.jupiter:junit-jupiter-params:5.5.2') 

2 Comments

I excluded 'junit-vintage-engine' from spring-boot-starter-test dependency but then the test even failed to start and was just greyed out in the test run window
@sunnyarya, Please check out your dependency tree, and check whether the 'junit-vintage-engine' module exists in your classpath, its a working solution for many, I don't sure on what basis, the answer has been downvoted
7

I fixed the same error by using the Maven dependency analyzer and searching for 'junit'. A 1st party dependency (the red bar) was bringing in json-simple which was bringing in a 4.10 junit dependency. Simply excluding the 4.10 junit (right-click + Exclude) fixed it.

screenshot of maven helper

Comments

3

Excluding the dependencies is not an option for us. Because with that we don't have our tests run. So our solution was to downgrade the JUnit version:

<!-- junit-vintage-engine 5.5.2 version does not support junit 4.13.1. If we try to use it, a parsing error is thrown. So we downgrade JUnit, so that junit-vintage-engine will handle it. --> <version.legacy.junit>4.13</version.legacy.junit> 

Using Spring Boot 2.3.4 seems to be working.

4 Comments

Unfortunately JUnit versions before 4.13.1 have a security vulnerability: nvd.nist.gov/vuln/detail/CVE-2020-15250
Unfortunately if we try to do the opposite, upgrading the junit-vintage-engine, we got the error: ``` bash [ERROR] TestEngine with ID 'junit-vintage' failed to discover tests ``` So the security vulnerability seems to be the best we can have at the moment.
You need to use the BOM junit-bom I think to get all your JUnit5 dependencies to 5.7.0. I you are only using JUnit4 you can also exclude junit-jupiter, junit-vintage-engine and mockito-junit-jupiter from spring-boot-starter-test.
We tried and it didn't work... if you are interested see the discussion here: github.com/hibernate/hibernate-search/pull/2409
3

Another reason for this error message could be a mixed junit-version set:

enter image description here

After consistently switching from junit 5.6.2 to 5.7.2 fixes the error for me.

Comments

2

In my case in gradle this error was caused by having

testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}" 

instead of

testImplementation "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}" 

Comments

2

use this version of platform runner 1.9.0 for junit 5 version 5.9.0

<junit.jupiter.version>5.9.0</junit.jupiter.version> 

and

<dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-runner</artifactId> <version>1.9.0</version> <scope>test</scope> </dependency> 

Comments

1

What solve my problem in this case, is changing Settings of IntelliJ, to use Gradle not Intellij as Gradle builder.

enter image description here

Comments

1

Similar issue can be observed for "junit-jupiter" test engine, in case of running tests located inside java9 named modules (also for Spring Boot app). The message is the same without clue about the reason:

TestEngine with ID "junit-jupiter" failed to discover tests 

The problem in this case is that one of your test classes requires named java9 module which is not required in your module-info.java.

To confirm this go to that particular module and execute build with -X option to enable debugging stacktraces. After that you will get more detailed information on the problem:

[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: There was an error in the forked process [ERROR] TestEngine with ID 'junit-jupiter' failed to discover tests [ERROR] org.junit.platform.commons.JUnitException: TestEngine with ID 'junit-jupiter' failed to discover tests (...) [ERROR] Caused by: org.junit.platform.commons.JUnitException: ClassSelector [className = 'x.y.z.YourTest'] resolution failed [ERROR] at org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener.selectorProcessed(AbortOnFailureLauncherDiscoveryListener.java:39) (...) [ERROR] Caused by: java.lang.IllegalAccessError: class x.y.z.YourTest (in module com.your.module) cannot access class com.fasterxml.jackson.core.JsonProcessingException (in module com.fasterxml.jackson.core) because module com.bnymellon.rei.data.exchange.au th.service does not read module com.fasterxml.jackson.core 

As the message says jackson.core is not available and needs to be added to your module descriptor module-info.java:

open module com.your.module { (...) requires com.fasterxml.jackson.core; requires com.fasterxml.jackson.databind; } 

NOTE: In example above you can see also jackson.databind added as subsequent exceptions (after you rerun maven build) would most probably suggest that this one is missing as well.

Comments

1

In case anyone is still having this issue, the above did not work for me. My solution involved using the latest spring boot test dependency, and then including the class name in the spring boot test annotation as shown below. I removed all my previous junit exclusions and explicit dependencies.

@SpringBootTest(classes = {testclass.class}) 
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <version>2.6.2</version> </dependency> 

Comments

0

Already had the exclusion in my pom for junit-vintage-engine, but was encountering the issue. Did invalidate cache and restart in IntelliJ to make it work.

Comments

0

For me nothing from above worked. However, adding the latest version of JUnit from maven solved the issue for me.

Comments

0

Nothing worked for me in the previous answers. But I removed the "reuseForks" in configuration of maven surefire plugin and upgraded it from 2.22.0 to 2.22.2.

Comments

0

I had excluded the test from the IntelliJ compilation by mistake.

This worked for me: Preferences > Build, Execution, Deployment > Compiler > Excludes and then removing the excluded test from the list.

Comments

0

In my case, adding to the configuration section of maven-failsafe-plugin option:

<classesDirectory>${project.build.outputDirectory}</classesDirectory> 

solved the issue.

Comments

0

I am using STS 4.19 and had this problem with a legacy code. So i delete the junit.jar old file from buildpath and it worked fine. Hope it works for you.

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
0

my solution removed following dependency:

<dependency> <groupId>junit-addons</groupId> <artifactId>junit-addons</artifactId> <scope>test</scope> </dependency> 

Comments

0

I have the same problem with:

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> </parent> 

This gives me the warning.

WARNING: TestEngine with ID 'junit-vintage' failed to discover tests java.lang.NoClassDefFoundError 

For me, this is important because I have to run both JUnit 4 and JUnit 5 tests. And this warning makes me not able to read JUnit 4 tests.

I tried solutions from all over the internet and I found the solution from

https://youtrack.jetbrains.com/issue/IDEA-257728/TestEngine-with-ID-junit-vintage-failed-to-discover-tests-failed-to-parse-version-of-junitjunit-4.13.1

Basically, we need to add

<dependencyManagement> <dependencies> <dependency> <groupId>org.junit</groupId> <artifactId>junit-bom</artifactId> <version>5.8.1</version> <!-- Adjust this with your case --> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 

And don't forget to make the build plugin just like this

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.1.2</version> </plugin> 

This makes me able to run both JUnit 4 and JUnit 5 tests 👍

Hope you all don't waste your time like I did. Spent like all day for this 😅

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.