Fixing the NoSuchMethodError JUnit Error – 修复NoSuchMethodError JUnit错误

最后修改: 2021年 5月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we’re going to learn how to fix the NoSuchMethodError and NoClassDefFoundError JUnit errors. Such problems usually occur when we have two different JUnit versions in our classpath. This situation may occur, for example, when the project’s JUnit version is different from the one that is used in a Maven or Gradle dependency.

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

2. JUnit’s NoClassDefFoundError in a Spring Project

2.JUnit的NoClassDefFoundError在Spring项目中

Let’s say that we have a Maven project using Spring Boot 2.1.2 and the Spring Boot Starter Test dependency. With such dependency, we can write and run automated tests using JUnit 5.3.2, which is the JUnit version of the spring-boot-test dependency.

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

Now, suppose we’ll continue using Spring Boot 2.1.2. However, we want to use JUnit 5.7.1. A possible approach would be the inclusion of the junit-jupiter-api, junit-jupiter-params, junit-jupiter-engine, and junit-platform-launcher dependencies in our pom.xml file:

现在,假设我们将继续使用Spring Boot 2.1.2。但是,我们想使用JUnit 5.7.1。一个可能的方法是在我们的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>
...

Nevertheless, in this case, we’ll get a NoClassDefFoundError when we run our tests:

尽管如此,在这种情况下,当我们运行测试时,我们会得到一个NoClassDefFoundError

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

Instead of the NoClassDefFoundError, a NoSuchMethodError will occur if we migrate to JUnit 5.4.0.

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

3. Understanding and Fixing the Error

3.了解并修复错误

As illustrated in the previous section, we ended up with a NoClassDefFoundError when we tried to migrate our JUnit version from 5.3.2 to 5.7.1.

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

The error occurred because our classpath ended up having two different versions of JUnit. Therefore, our project was compiled with a newer version of JUnit (5.7.1) but found an older version (5.3.2) at runtime. As a result, the JUnit launcher tried to use a class that is not available in the older version of JUnit.

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

Next, we’re going to learn different solutions for fixing this error.

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

3.1. Overriding the JUnit Version of Spring

3.1.重写Spring的JUnit版本

An effective approach for fixing the error in our example is to override the JUnit version managed by Spring:

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

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

Now, we can also replace our JUnit dependencies with the following one:

现在,我们也可以把我们的JUnit依赖关系替换成以下的依赖关系。

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

This single dependency will include junit-jupiter-api, junit-jupiter-params, and junit-jupiter-engine. The junit-platform-launcher dependency is usually necessary only when we need to run our JUnit tests programmatically.

这个单一的依赖将包括junit-jupiter-apijunit-jupiter-params,和junit-jupiter-engine。通常只有在我们需要以编程方式运行我们的 JUnit 测试时,才需要依赖junit-platform-launcher

Similarly, we can also override the managed version in a Gradle project:

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

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

3.2. Solution for Any Project

3.2.任何项目的解决方案

In the previous section, we learned how to fix the NoSuchMethodError and NoClassDefFoundError JUnit errors in a Spring project, which is the most common scenario. However, if these errors are happening and our project does not use Spring, we can try to fix the collision of dependencies in Maven.

在上一节中,我们学习了如何修复Spring项目中的NoSuchMethodErrorNoClassDefFoundError JUnit错误,这是最常见的情况。不过,如果这些错误发生了,而我们的项目没有使用Spring,我们可以尝试修复Maven中的依赖关系的碰撞

Similar to what happened in our example with Spring, a project may have multiple versions of JUnit due to transitive dependencies. For such a scenario, we have a detailed tutorial on how to resolve the collisions in Maven.

与我们在Spring的例子中发生的情况类似,一个项目可能会因为横向依赖关系而出现多个JUnit版本。对于这种情况,我们有一个详细的教程,介绍如何在Maven中解决碰撞问题

4. Conclusion

4.总结

In this tutorial, we reproduced and learned how to fix the NoSuchMethodError and NoClassDefFoundError JUnit errors. The code snippets, as always, can be found over on GitHub. Please notice that, in this source code example, we override the JUnit version in the pom.xml file of the parent project.

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