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
родительского проекта .