Перейти к основному содержимому

Исправление ошибки NoSuchMethodError JUnit

· 3 мин. чтения

1. Обзор

В этой статье мы узнаем, как исправить ошибки JUnit NoSuchMethodError и NoClassDefFoundError . Такие проблемы обычно возникают, когда у нас есть две разные версии JUnit в нашем пути к классам . Такая ситуация может возникнуть, например, когда версия JUnit проекта отличается от той, которая используется в зависимости Maven или Gradle.

2. JUnit NoClassDefFoundError в проекте Spring

Допустим, у нас есть проект Maven, использующий Spring Boot 2.1.2 и зависимость Spring Boot Starter Test . С такой зависимостью мы можем писать и запускать автоматические тесты, используя JUnit 5.3.2, который является JUnit-версией зависимости spring-boot-test .

Теперь предположим, что мы продолжим использовать Spring Boot 2.1.2. Однако мы хотим использовать JUnit 5.7.1. Возможным подходом было бы включение зависимостей junit-jupiter-api , junit-jupiter-params , junit-jupiter-engine и junit-platform-launcher в наш файл pom.xml :

<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

Вместо NoClassDefFoundError произойдет NoSuchMethodError , если мы перейдем на JUnit 5.4.0.

3. Понимание и исправление ошибки

Как показано в предыдущем разделе, мы получили ошибку NoClassDefFoundError , когда попытались перенести нашу версию JUnit с 5.3.2 на 5.7.1.

Ошибка произошла из-за того, что наш путь к классам оказался с двумя разными версиями JUnit . Поэтому наш проект был скомпилирован с более новой версией JUnit (5.7.1), но во время выполнения обнаружил более старую версию (5.3.2). В результате средство запуска JUnit попыталось использовать класс, недоступный в более старой версии JUnit.

Далее мы собираемся изучить различные решения для исправления этой ошибки.

3.1. Переопределение версии Spring для JUnit

Эффективный подход к исправлению ошибки в нашем примере — переопределить версию JUnit, управляемую Spring:

<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-api , junit-jupiter-params и junit-jupiter-engine . Зависимость junit-platform-launcher обычно необходима только тогда, когда нам нужно программно запустить наши тесты JUnit .

Точно так же мы также можем переопределить управляемую версию в проекте Gradle :

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

3.2. Решение для любого проекта

В предыдущем разделе мы узнали, как исправить ошибки JUnit NoSuchMethodError и NoClassDefFoundError в проекте Spring, что является наиболее распространенным сценарием. Однако, если эти ошибки случаются и наш проект не использует Spring, мы можем попробовать исправить коллизию зависимостей в Maven .

Подобно тому, что произошло в нашем примере со Spring, проект может иметь несколько версий JUnit из-за транзитивных зависимостей . Для такого сценария у нас есть подробное руководство по разрешению коллизий в Maven .

4. Вывод

В этом руководстве мы воспроизвели и узнали, как исправить ошибки JUnit NoSuchMethodError и NoClassDefFoundError . Фрагменты кода, как всегда, можно найти на GitHub . Обратите внимание, что в этом примере исходного кода мы переопределяем версию JUnit в файле pom.xml родительского проекта .