В чем разница между JUnit4 и JUnit5
Что проверяют
Знаете ли вы, чем JUnit 5 отличается устройством, а не только новыми именами аннотаций, и понимаете ли, где в Android он реально применим. Следом почти всегда спрашивают, можно ли писать на JUnit 5 инструментальные тесты и что делать с уже написанными тестами на JUnit 4.
Как отвечать
Начните с архитектуры. JUnit 4 это одна библиотека с раннерами и правилами. JUnit 5 состоит из трёх частей:
- JUnit Platform: движок запуска, через который тесты находят Gradle и IDE;
- JUnit Jupiter: новая модель написания тестов, пакет
org.junit.jupiter.api; - JUnit Vintage: движок, который запускает старые тесты JUnit 4 на платформе.
Дальше соответствие аннотаций: @Before/@After стали @BeforeEach/@AfterEach, @BeforeClass/@AfterClass стали @BeforeAll/@AfterAll, @Ignore стал @Disabled, категории заменил @Tag. Вместо @RunWith и @Rule одна модель расширений @ExtendWith. Исключения проверяются через assertThrows, а не @Test(expected = ...). Появились @ParameterizedTest с @CsvSource и @MethodSource, @Nested, @DisplayName.
Главное для Android. Локальные тесты в src/test (ViewModel, use case, репозитории) спокойно переводятся на Jupiter: подключаете зависимости и включаете useJUnitPlatform() в testOptions. А инструментальные тесты идут через AndroidJUnitRunner, построенный на JUnit 4. На нём же держатся createComposeRule(), ActivityScenarioRule и RobolectricTestRunner. Официальной поддержки JUnit 5 для них нет, только сторонний Gradle-плагин. Поэтому в реальном проекте обычно живут обе версии.
Где спотыкаются
Смешивают импорты org.junit.Test и org.junit.jupiter.api.Test. После включения useJUnitPlatform() без Vintage тесты JUnit 4 просто перестают запускаться, а сборка остаётся зелёной.
В Kotlin вешают @BeforeAll на обычный метод. Он должен быть статическим: нужен companion object с @JvmStatic или @TestInstance(Lifecycle.PER_CLASS).
Утверждают, что JUnit 5 полностью заменил JUnit 4 в Android. Для Compose UI, Espresso и Robolectric это неправда.