1. 概述

在本文中,我们将 学习如何修复 NoSuchMethodErrorNoClassDefFoundError JUnit 错误 。当类 路径 中有两个不同的 JUnit 版本时,通常会出现此类问题。例如,当项目的 JUnit 版本与 Maven 或 Gradle 依赖项中使用的版本不同时,可能会出现这种情况。

2. Spring项目中JUnit的 NoClassDefFoundError

假设我们有一个使用 Spring Boot 2.1.2 和Spring Boot Starter Test依赖项的 Maven 项目。有了这样的依赖,我们可以使用 JUnit 5.3.2 编写和运行自动化测试,这是 spring-boot-test 依赖的 JUnit 版本。

现在,假设我们将继续使用 Spring Boot 2.1.2。但是,我们想要使用 JUnit 5.7.1。一种可能的方法是在 pom.xml 文件中包含 junit-jupiter-apijunit-jupiter-paramsjunit-jupiter-enginejunit-platform-launcher 依赖项:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.7.1</version>
    <scope>test</scope>
</dependency>
...

然而,在这种情况下,当我们运行测试时,我们会得到一个 NoClassDefFoundError

[ERROR] java.lang.NoClassDefFoundError: org/junit/platform/commons/util/ClassNamePatternFilterUtils

如果我们迁移到 JUnit 5.4.0,将会出现 NoSuchMethodError ,而不是 NoClassDefFoundError

3. 理解并修复错误

如上一节所示,当我们尝试将 JUnit 版本从 5.3.2 迁移到 5.7.1 时,我们最终遇到了 NoClassDefFoundError

发生错误是因为 我们的 类路径 最终有两个不同版本的 JUnit 。因此,我们的项目是使用较新版本的 JUnit (5.7.1) 编译的,但在运行时发现了较旧版本 (5.3.2)。因此,JUnit 启动器尝试使用旧版本 JUnit 中不可用的类。

接下来,我们将学习修复此错误的不同解决方案。

3.1.覆盖 Spring 的 JUnit 版本

修复我们示例中的错误的有效方法是覆盖 Spring 管理的 JUnit 版本:

<properties>
    <junit-jupiter.version>5.7.1</junit-jupiter.version>
</properties>

现在,我们还可以将 JUnit 依赖项替换为以下依赖项:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
</dependency>

这个单一依赖项将包括 junit-jupiter-apijunit-jupiter-paramsjunit-jupiter-engine 。通常仅当我们需要以编程方式运行 JUnit 测试时才需要 junit-platform-launcher 依赖项。

同样, 我们也可以在 Gradle 项目中覆盖托管版本

ext['junit-jupiter.version'] = '5.7.1'

3.2.适用于任何项目的解决方案

在上一节中,我们学习了如何修复 Spring 项目中的 NoSuchMethodErrorNoClassDefFoundError JUnit 错误,这是最常见的场景。但是,如果发生这些错误并且我们的项目没有使用 Spring,我们可以尝试 修复 Maven 中的依赖冲突

与我们在 Spring 示例中发生的情况类似, 由于传递依赖关系,一个项目可能具有多个版本的 JUnit 。对于这样的场景,我们有一个关于如何解决 Maven 中的冲突的详细教程

4。结论

在本教程中,我们重现并学习了如何修复 NoSuchMethodErrorNoClassDefFoundError JUnit 错误。与往常一样,代码片段可以 在 GitHub 上找到。请注意,在此源代码示例中,我们覆盖了父项目pom.xml 文件中的 JUnit 版本。