NoSuchMethodError: 'java.util.Set org.junit.platform.engine.TestDescriptor.getAncestors() 运行 Spock Spring Boot 单元测试时

问题描述 投票:0回答:1

背景

我有一个使用 Spock 测试框架编写的单元测试来测试我的 Spring Boot 应用程序。 我已经声明了以下测试依赖项:

  • spock-spring
    :2.3-groovy-4.0
  • spring-boot-starter-test
    :3.2.4
  • surefire plugin version
    :3.2.2

症状

当我运行

mvn test
时,surefire插件无法执行它们,并给出错误:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.2.2:test (default-test) on project spockdata: 
[ERROR] 
[ERROR] Please refer to C:\Users\myfolder\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.
There was an error in the forked process
'java.util.Set org.junit.platform.engine.TestDescriptor.getAncestors()'

我做了什么?

我按照surefire的说明查看了它创建的surefire转储文件,并看到了错误:

java.lang.NoSuchMethodError: 'java.util.Set org.junit.platform.engine.TestDescriptor.getAncestors()'
    at org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener.getTestClassNames(StackTracePruningEngineExecutionListener.java:50)

我尝试声明 Spock 的物料清单,

spock-bom
以确保 Spock 的依赖关系一致,但这没有帮助:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.spockframework</groupId>
                <artifactId>spock-bom</artifactId>
                <version>2.3-groovy-4.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

我也在没有声明

spock-bom
的情况下进行了测试,但仍然收到此错误。

我该如何解决这个问题以及为什么会发生这种情况?

java spring-boot maven junit spock
1个回答
0
投票

我们如何解决这个问题?

异常中的类

TestDescriptor
来自
org.junit.platform.engine
包。

让我们运行

mvn dependency:tree
(或者 Maven Helper 插件,如果使用 IntelliJ)来查看我们声明的两个依赖项是否有多个版本的 org.junit.platform 组组件:

  • spring-boot-starter-测试
  • 斯波克弹簧
[INFO] --- dependency:3.6.1:tree (default-cli) @ myspockspringtest ---
...
[INFO] |  +- org.junit.jupiter:junit-jupiter:jar:5.10.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-api:jar:5.10.2:test
[INFO] |  |  |  +- org.opentest4j:opentest4j:jar:1.3.0:test
[INFO] |  |  |  +- org.junit.platform:junit-platform-commons:jar:1.10.2:test
[INFO] |  |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-params:jar:5.10.2:test
[INFO] |  |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.10.2:test
...
[INFO] +- org.spockframework:spock-spring:jar:2.3-groovy-4.0:test
[INFO] |  +- org.spockframework:spock-core:jar:2.3-groovy-4.0:test
[INFO] |  |  \- org.junit.platform:junit-platform-engine:jar:1.9.0:test

由此我们可以看出

spock-spring
junit-platform-engine
org.junit.platform:junit-platform-engine:jar:1.9.0:test

看看

spring-boot-starter-test
,它包含一个类似的 1.x 版本
1.10.2
org.junit.platform:junit-platform-commons:jar:1.10.2:test
所以也许这两者是冲突的。

我们还可以在 IntelliJ 中使用

Ctrl+N
来查找
TestDescriptor
以查看它来自哪个工件。这告诉我们
TestDescriptor
住在
junit-platform-engine-1.9.0
罐子里。

Maven 如何解析要使用哪个依赖项?

当存在冲突时,Maven 会在树中映射出依赖关系,并选择到达它的跳数最少的依赖关系。 如果仍然存在冲突,Maven 将选择 pom 中第一个声明的那个。

在这种情况下,来自 spock-spring 的

junit-platform-engine
在层次结构中更接近根(spock-spring 为 3 跳,而 spring-boot-starter-test 为 4 跳),因此 Maven 选择了 Spock 的 1.9.0 依赖项
junit-platform-engine

因此,我们有以下不匹配导致 1.9.0 引擎找到 1.10.2 中不再存在的方法:

  • junit-平台-commons:1.10.2
  • junit 平台引擎:1.9.0

那么,我们该如何解决呢?我们有两个选择

  1. 使用 Maven 排除元素从 spock-spring 中排除 junit-platform-engine,以便只有 spring-boot-starter-test 中的引擎可用: 从 spock-spring 中排除 junit-platform-engine:
        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-spring</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.platform</groupId>
                    <artifactId>junit-platform-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

或者 2. 包含 Spring Boot 物料清单(带或不带 Spock BOM):

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.spockframework</groupId>
                <artifactId>spock-bom</artifactId>
                <version>2.3-groovy-4.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>3.2.4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

完成此操作后,这些组件的

mvn dependency:tree
现在看起来像:

[INFO] --- dependency:3.6.1:tree (default-cli) @ myspockspringtest ---
...
[INFO] |  +- org.junit.jupiter:junit-jupiter:jar:5.10.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-api:jar:5.10.2:test
[INFO] |  |  |  +- org.opentest4j:opentest4j:jar:1.3.0:test
[INFO] |  |  |  +- org.junit.platform:junit-platform-commons:jar:1.10.2:test
[INFO] |  |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-params:jar:5.10.2:test
[INFO] |  |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.10.2:test
[INFO] |  |     \- org.junit.platform:junit-platform-engine:jar:1.10.2:test
...
[INFO] +- org.spockframework:spock-spring:jar:2.3-groovy-4.0:test
[INFO] |  +- org.spockframework:spock-core:jar:2.3-groovy-4.0:test
[INFO] |  \- org.apache.groovy:groovy:jar:4.0.4:test
...

由此我们可以得出结论,junit-platform v1.9中的TestDescriptor.getAncestors()方法在v1.10中被删除了。

为了解决这个问题,我们通过将 junit 的依赖项从我们的依赖项中排除或导入声明所有依赖项的物料清单来确保它们全部同步。

© www.soinside.com 2019 - 2024. All rights reserved.