Спустя восемь лет после JUnit 5 выходит новая версия популярного фреймворка. JUnit 6 — это не просто обновление, а переход к современной экосистеме Java и Kotlin. В новом переводе от команды Spring АйО узнаем, что новая версия требует Java 17+, унифицирует версии компонентов, удаляет deprecated API и внедряет поддержку JSpecify для строгого null-safety.
JUnit 6 вышел спустя восемь лет после релиза JUnit 5. Это не просто очередное обновление — это значительный шаг вперёд в направлении модернизации.
Рассмотрим основные улучшения, и изменения, ломающие обратную совместимость.
JUnit 6 требует Java 17+ (и Kotlin 2.2+)
JUnit 6 повышает минимальную требуемую версию Java с 8 до 17. Это изменение обусловлено двумя ключевымифакторами:
Развитие Java: с момента выхода версии 8 было внедрено множество улучшений.
Переход экосистемы на Java 17.
Например:
Spring Framework 6 и Spring Boot 3 перешли на базовую поддержку Java 17+.
AssertJ также перешёл на Java 17+.
Для проектов, которые всё ещё используют версии Java до 17, JUnit 5 будет поддерживаться как минимум ещё в течение одного года.
Для пользователей Kotlin JUnit 6 теперь требует версию Kotlin 2.2 или новее.
JUnit Platform, Jupiter и Vintage теперь имеют единую версию
Фреймворк JUnit состоит из трёх основных архитектурных компонентов:
Platform — предоставляет API движка для запуска тестов.
Jupiter — предоставляет API для написания тестов.
Vintage — реализует движок, позволяющий запускать тесты, написанные с использованием JUnit 3 и 4.
Однако в JUnit 5 только артефакты Jupiter и Vintage выпускались под одной и той же версией, тогда как артефакты Platform использовали отдельную схему версионирования.
Например:
junit-jupiter-engine:5.13.3
junit-vintage-engine:5.13.3
junit-platform-engine:1.13.3
Как видно, версия junit-platform-engine
отличается от остальных.
Для упрощения управления зависимостями в JUnit 6 версия теперь унифицирована для всех компонентов. Это означает, что все три части, включая JUnit Platform, будут выпускаться под одной и той же версией.
В результате после миграции на JUnit 6 можно использовать единую версию:
junit-jupiter-engine:6.0.0
junit-vintage-engine:6.0.0
junit-platform-engine:6.0.0
Различные улучшения и устаревшие API
JUnit 6 представляет собой значительную переработку кодовой базы за счёт удаления deprecated API и кода, а также внедрения ряда улучшений.
Новые функции и улучшения API:
-
Модификатор
suspend
в Kotlin теперь может применяться к методам тестов и жизненного цикла.
Комментарий от эксперта Spring АйО Михаила Поливахи:
Для тех, кому любопытно, в движке Junit вызов@Test
метода, который помечен модификаторомsuspend
, реализован через простойrunBlocking
вызов.https://github.com/junit-team/junit-framework/pull/4530/files#diff-be2eb6e242e221ae7e4bc2ee1c53de6f0cb987ae91bbc30953cbd43ff1b4e852R55
Названия для
@ParameterizedClass
и@ParameterizedTest
теперь оформляются в едином стиле: пары «имя = значение» отображаются с пробелами — например,fruit = apple
вместоfruit=apple
.Для согласованности с методами тестов, классы
@Nested
, объявленные в одном и том же внешнем классе или интерфейсе, теперь упорядочиваются детерминированным, но намеренно неочевидным способом.
Устаревшие и удалённые элементы публичного API:
Значения
enum
JRE отJAVA_8
доJAVA_16
объявлены deprecated, так как они больше не поддерживаются в runtime — новая базовая версия Java теперьJAVA_17
.Аннотации
@EnabledForJreRange
и@DisabledForJreRange
теперь по умолчанию используют JAVA_17 в качестве минимального значения.Класс
MethodOrderer.Alphanumeric
удалён.Метод
ReflectionSupport.loadClass(String)
удалён.Метод
ReflectionUtils.readFieldValue(…)
удалён.Метод
ReflectionUtils.getMethod(…)
удалён.Метод
InvocationInterceptor.interceptDynamicTest(Invocation, ExtensionContext)
удалён.Движок JUnit Vintage теперь помечен как deprecated и будет фиксировать проблему на уровне INFO при обнаружении хотя бы одного тестового класса JUnit 4.
Удаление модулей и интеграции
Модули
junit-platform-runner
иjunit-platform-jfr
были удалены. Функциональность JFR теперь интегрирована в модульjunit-platform-launcher
.Модуль
junit-platform-suite-commons
теперь включён в составjunit-platform-suite
.Артефакт
junit-jupiter-migrationsupport
и содержащиеся в нём классы объявлены как deprecated и будут удалены в следующей мажорной версии.
Совместимость со сборочными инструментами:
Поддержка Maven Surefire/Failsafe версий ниже 3.0.0 прекращена.
Полный список изменений доступен в официальных release notes.
Более стабильный и производительный парсинг CSV для @CsvSource и @CsvFileSource
JUnit 6 перешёл с библиотеки univocity-parsers, которая больше не поддерживается, на FastCSV для обработки CSV-данных.
Это обеспечивает:
Более стабильную обработку CSV-входных данных (в том числе с ошибками в формате).
Улучшенную диагностику ошибок.
Хотя общее поведение остаётся в значительной степени совместимым с JUnit 5, есть несколько изменений, которые могут потребовать адаптации тестов или входных файлов:
Атрибут
lineSeparator
в@CsvFileSource
удалён. Разделитель строк теперь определяется автоматически — допускаются любые из \r,\n
или\r\n
.Лишние символы после закрывающей кавычки больше не допускаются в
@CsvSource
и@CsvFileSource
. Например, если используется одинарная кавычка как символ кавычек, то значениеCSV 'foo’INVALID,'bar'
теперь вызовет исключение. Это предотвращает тихую обработку некорректного ввода.Атрибуты вроде
ignoreLeadingAndTrailingWhitespace
,nullValues
и другие в@CsvSource
и@CsvFileSource
теперь применяются не только к обычным значениям, но и к заголовкам.Тексты исключений и причины ошибок при обработке некорректного CSV-ввода могут отличаться от прежних.
Если в ваших тестах используются сложные или нестандартно отформатированные CSV-данные, рекомендуется их проверить и при необходимости скорректировать после миграции.
JUnit 6 улучшает работу с null-safety благодаря аннотациям JSpecify
В JUnit 5 информация о null-safety передавалась неформально через JavaDoc — это было полезно для разработчиков, но недоступно для инструментов. В результате возникали типичные проблемы:
NullPointerException
в runtime.Дополнительные преобразования типов или проверки на
null
в Kotlin из-за различий между nullable и non-nullable типами.
JUnit 6 решает эти проблемы с помощью поддержки аннотаций JSpecify. Эти аннотации:
Распознаются в IDE.
Поддерживаются инструментами статического анализа, такими как ErrorProne и NullAway.
Начиная с JUnit 6, все публичные API последовательно указывают информацию о null-safety с помощью аннотации @Nullable
.
Например, метод Arguments.of()
теперь явно показывает, что принимает аргументы, которые могут быть равны null
, но всегда возвращает ненулевое значение:
static Arguments of(@Nullable Object... arguments) {
return of(arguments);
}
Типы без аннотаций по умолчанию считаются non-nullable.
Заключение
JUnit 6 представляет собой значительный этап в развитии фреймворка. Хотя это не полная переработка, как в случае с JUnit 5, новая версия предлагает ряд существенных улучшений за счёт:
использования современных возможностей языка Java;
внедрения полноценной null-safety с помощью JSpecify;
упрощения управления зависимостями.

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.