108

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?

starball
  • 20,030
  • 7
  • 43
  • 238
Ivan dal Bosco
  • 3,233
  • 4
  • 19
  • 24

23 Answers23

126

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>
Ivan dal Bosco
  • 3,233
  • 4
  • 19
  • 24
  • 6
    this dependency is really troublesome. I already had these exclusions. junit junit com.vaadin.external.google android-json – Chhorn Elit Jun 23 '20 at 05:58
  • 1
    Yo it works! Thanks man. Had the same problem! – MrHunchoJack May 02 '21 at 17:51
  • 1
    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. – Palo Mar 22 '23 at 17:56
46

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>
David Buck
  • 3,752
  • 35
  • 31
  • 35
Kashish Bhatia
  • 461
  • 4
  • 3
16

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 trying to run some Spock tests and the required Groovy XML dependency was not found (see stack trace below). It was solved when I added the Groovy dependency explicitly.

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)
...
Saikat
  • 14,222
  • 20
  • 104
  • 125
  • 5
    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. – Amadeu Barbosa Dec 30 '21 at 12:18
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")
    }
}
Mircea Stanciu
  • 3,675
  • 3
  • 34
  • 37
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')

Prasanth Rajendran
  • 4,570
  • 2
  • 42
  • 59
  • 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 – sunny arya Aug 04 '20 at 04:20
  • @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 – Prasanth Rajendran Aug 04 '20 at 04:51
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.

Sorin Dumitru
  • 99
  • 1
  • 3
8

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

File > Invalidate Cache > Invalidate and Restart

enter image description here

Ali Malek
  • 578
  • 8
  • 26
5

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

Jason Crease
  • 1,896
  • 17
  • 17
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.

fax4ever
  • 81
  • 3
  • Unfortunately JUnit versions before 4.13.1 have a security vulnerability: https://nvd.nist.gov/vuln/detail/CVE-2020-15250 – Nyamiou The Galeanthrope Oct 16 '20 at 13:25
  • 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. – fax4ever Oct 20 '20 at 05:28
  • 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. – Nyamiou The Galeanthrope Oct 21 '20 at 12:36
  • We tried and it didn't work... if you are interested see the discussion here: https://github.com/hibernate/hibernate-search/pull/2409 – fax4ever Oct 23 '20 at 10:43
2

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.

Dirk
  • 1,064
  • 1
  • 11
  • 13
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

WesternGun
  • 11,303
  • 6
  • 88
  • 157
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.

walkeros
  • 4,736
  • 4
  • 35
  • 47
1

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}"
ununiform
  • 406
  • 5
  • 6
1

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>

&
<dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-runner</artifactId>
            <version>1.9.0</version>
            <scope>test</scope>
        </dependency>
kpgan8204
  • 91
  • 1
  • 3
0

my solution removed following dependency:

<dependency>
    <groupId>junit-addons</groupId>
    <artifactId>junit-addons</artifactId>
    <scope>test</scope>
</dependency>
xMilos
  • 1,519
  • 4
  • 21
  • 36
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.

hmims
  • 539
  • 8
  • 28
0

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

AhmedRana
  • 486
  • 9
  • 22
0

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>
zen
  • 591
  • 1
  • 4
  • 5
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.

DeenOub
  • 365
  • 1
  • 4
  • 13
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.

crazyGuy
  • 338
  • 2
  • 15
0

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

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

solved the issue.

Andrey Lebedenko
  • 1,850
  • 17
  • 24
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.

  • 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](/help/how-to-answer). – Community Aug 28 '23 at 13:57
-1

I ran into this situation with a project that worked fine a few months ago, but when I went back the unit tests no longer worked within IntelliJ. I restarted IntelliJ, no change, updated IntelliJ and "Wala" error went away.

  • Seems the original poster found a fix, not related to updating existing component. You are right that the error you saw may have been the same as described in original question, but that error is a very generic one, and not a strong signal. So you should provide a bit more evidence that your fix is actually relevant to his/her problem. – BobHy May 18 '21 at 20:16