使用Spring Boot 2.2时出现错误"TestEngine with ID 'junit-vintage' failed to discover tests"。

110

我有一个使用Spring Boot和Junit 5的简单应用程序:

  • 当使用Spring Boot 2.1(例如2.1.8或2.1.12)时,我的单元测试可以顺利运行。

  • 当使用Spring Boot 2.2(例如2.2.2.RELEASE或2.3.2.RELEASE)时,我的单元测试失败并出现错误消息。

[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)

我正在使用Maven 3.6.1,JDK 1.8,JUnit 5.6.0和JUnit平台1.6.0。我从“spring-boot-starter-test”中排除了对“junit:junit”的依赖项,因此在依赖树中没有剩余的JUnit 4构件。请注意,Spring Boot 2.2和2.3都使用maven-surefire-plugin 2.22.2,因此我的问题不是源自maven-surefire-plugin的任何回归。
为了让我的单元测试工作,我应该坚持使用Spring Boot 2.1吗?

这意味着“mvn”正在使用错误的JDK 11,而不是15。 - Jordan Stewart
我在pom.xml文件中有配置错误,这个答案帮了我大忙 - Ahmed M. Elzubair
23个回答

127

我找到了错误。对于spring-boot-starter-test的依赖会引入junit-vintage-engine的依赖。必须排除后者:

<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>

6
这个依赖关系真的很麻烦。 我已经有了这些排除项。 junit junit com.vaadin.external.google android-json - Chhorn Elit
1
哟,它可以工作了!谢谢,伙计。我也遇到了同样的问题! - MrHunchoJack
1
这是唯一的正确解决方案。其他提出增加特定版本依赖的解决方案可能有效,但问题在于你会得到一个有错误版本的传递依赖关系,因此你必须按照此处所述进行排除。如果你想更好地理解问题,可以在调试模式下运行maven(mvn test -X)或打印依赖树(mvn dependency:tree),这也可能非常有用。我使用了不同的依赖项,我不得不排除junit-jupiter-api,所以请尝试检查依赖树。 - Palo

48

将以下依赖项显式地添加以升级 junit-vintage-engine 就可以解决问题:

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

在添加上述依赖项后,使Intellij缓存失效解决了我的问题。 - Patrick

18

最佳选项是使用调试模式运行Maven测试:

例如mvn clean test -X。它将显示精确的失败原因。

在我的情况下,我正在尝试运行一些Spock测试,但找不到所需的Groovy XML依赖项(请参见下面的堆栈跟踪)。当我显式地添加了Groovy依赖项时,问题得到了解决。

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)
...

5
我非常同意你的观点!在我的情况下,我也检查了来自surefire的转储文件,那里我发现了一个关于另一个类的臭名昭著的NoClassDefFoundError错误。你确实帮助了我。 - Amadeu Barbosa

10
在我的情况下(使用GRADLE和Spring Boot 2.x.x),添加排除 vintage 的内容起了作用。
configurations {
    all {
        exclude(group = "junit", module = "junit")
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
    }
}

9

我也遇到过这个问题。尝试过上面提到的不同解决方案,但都无济于事。唯一有效的方法是简单而可笑地重启Intellij。


9

对于问题中报告的错误或下面的错误,两者都涉及到同样的问题。

java.lang.NoClassDefFoundError: junit/runner/Version

如果项目依赖于spring-boot-starter-test,但是排除了或未包含JUnit 4,则会出现此错误。 spring-boot-starter-test默认依赖于junit-vintage-engine。要解决此问题,我们要么需要排除junit-vintage-engine,要么不依赖于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')


我从spring-boot-starter-test依赖中排除了“junit-vintage-engine”,但是测试甚至无法启动,并且在测试运行窗口中变灰。 - sunny arya
@sunnyarya,请检查您的依赖树,并检查您的类路径中是否存在“'junit-vintage-engine'”模块,这是许多工作解决方案之一。我不确定答案被投反对的依据是什么。 - Prasanth Rajendran

8
在我的情况下,问题是通过使 ide(IntelliJ)缓存无效来解决的。
文件 > 使缓存无效 > 使其无效并重新启动

enter image description here


5
我使用Maven依赖分析器搜索“junit”,解决了相同的错误。一个第一方依赖(红色条)引入了json-simple,它又引入了4.10 junit 依赖。 右键单击 + Exclude即可排除4.10 junit,问题得到解决。 maven helper的截图

3

对我们来说,排除依赖项并不是一个选项。因为这样做会导致我们的测试无法运行。 因此,我们的解决方案是将JUnit版本降级:

<!--
  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>

使用 Spring Boot 2.3.4 看起来可以正常工作。


很遗憾,JUnit 4.13.1之前的版本存在安全漏洞:https://nvd.nist.gov/vuln/detail/CVE-2020-15250 - Nyamiou The Galeanthrope
不幸的是,如果我们尝试相反的操作,升级junit-vintage-engine,我们会遇到错误:[ERROR] TestEngine with ID 'junit-vintage' failed to discover tests因此,目前看来安全漏洞似乎是我们能够拥有的最好的选择。 - fax4ever
你需要使用 BOM junit-bom 来获取所有 JUnit5 依赖项到 5.7.0 版本。如果你只使用 JUnit4,你还可以从 spring-boot-starter-test 中排除 junit-jupiter、junit-vintage-engine 和 mockito-junit-jupiter。 - Nyamiou The Galeanthrope
我们尝试过了,但没有成功... 如果您感兴趣,请查看此处的讨论:https://github.com/hibernate/hibernate-search/pull/2409 - fax4ever

2
在我的情况下,在Gradle中,这个错误是由以下原因造成的:
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}"

替代

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接