JUnit: що це, ключові поняття та як працює

Автор: IT Sectr Опубліковано: 2026-04-08 Час читання: 8 хв

JUnit — це стандартний фреймворк для модульного тестування в екосистемі Java та Kotlin, який використовується в Android-розробці для перевірки бізнес-логіки на рівні ізольованих компонентів. Фреймворк надає набір анотацій, assertion-методів та Test Runner для автоматичного виявлення та виконання тестів. За даними JUnit.org, бібліотека залишається найпопулярнішим рішенням для unit-тестування в JVM-екосистемі: понад 70% Java-проєктів використовують JUnit у будь-якій з версій.

Головне

  • JUnit — фреймворк для модульного тестування Java та Kotlin коду з відкритим вихідним кодом.
  • Анотації — @Test, @BeforeEach, @BeforeAll керують життєвим циклом тестового класу.
  • Assertions — assertEquals, assertTrue, assertThrows перевіряють очікувані результати виконання.
  • Параметризовані тести — дозволяють запускати один тест з різними наборами вхідних даних.
  • Test Runner — інфраструктура JUnit автоматично знаходить та запускає всі тести в проєкті.

Що таке JUnit?

JUnit — це фреймворк з відкритим вихідним кодом для написання та запуску повторюваних модульних тестів на мові Java та Kotlin. Він входить в екосистему xUnit — сімейства фреймворків, заснованих на архітектурі Kent Beck та Erich Gamma, і є стандартним інструментом тестування в Android Studio та IntelliJ IDEA.

Основне завдання JUnit — ізолювати невеликий фрагмент коду (метод, клас) і перевірити його поведінку в контрольованих умовах. Тести пишуться у вигляді звичайних Java/Kotlin класів з анотаціями, а фреймворк бере на себе виявлення тестів, управління їхнім життєвим циклом та збір статистики виконання.

Перша версія JUnit з'явилася в 1997 році і кардинально змінила підхід до розробки, популяризувавши практики Test-Driven Development (TDD). Сьогодні JUnit 5 (Jupiter) — актуальна версія, повністю перероблена під модульну архітектуру з підтримкою Java 8+ та розширень.

Як працює JUnit

Механізм виконання JUnit заснований на паттерні Test Runner, який сканує classpath, знаходить методи з анотацією @Test, створює екземпляр тестового класу та запускає методи в певному порядку. Test Runner керує життєвим циклом: виклик BeforeAll → BeforeEach → Test → AfterEach → AfterAll.

Життєвий цикл тестового класу

JUnit обгортає кожен тестовий метод в окремий екземпляр класу, що гарантує ізоляцію між тестами. Це означає, що поля класу не зберігають стан між різними @Test-методами — кожен тест починається з чистого об'єкта.

Базова структура тесту

Найпростіший тест на JUnit виглядає як метод з анотацією @Test, всередині якого викликається код, що тестується, і перевіряється результат через assertion. Якщо assertion не проходить — тест вважається таким, що впав, і JUnit повідомляє про помилку.

java
@Test
void additionShouldReturnCorrectSum() {
    var calculator = new Calculator();
    var result = calculator.add(2, 3);
    assertEquals(5, result);
}

Test Runner автоматично знаходить такий метод, запускає його та повідомляє результат. Якщо метод не викидає винятків — тест пройдено (green). Якщо assertion не спрацьовує — тест падає (red).

Анотації JUnit: життєвий цикл тесту

Анотації JUnit визначають, коли і як має виконуватися тестовий код. У JUnit 5 анотації знаходяться в пакеті org.junit.jupiter.api і покривають всі етапи: підготовку даних, виконання тесту, очищення ресурсів.

АнотаціяПризначенняВиконується
@TestПозначає тестовий методОдин раз на виклик
@BeforeEachПідготовка перед кожним тестомПеред кожним @Test
@BeforeAllОдноразова ініціалізація класуОдин раз перед усіма тестами
@AfterEachОчищення після кожного тестуПісля кожного @Test
@AfterAllОдноразове завершення класуОдин раз після всіх тестів
@DisplayNameЛюдиночитане ім'я тестуДекорація

Приклад використання анотацій

Розглянемо повний тестовий клас з коректним життєвим циклом. Метод setUp створює свіжий екземпляр Calculator перед кожним тестом, а tearDown звільняє ресурси — наприклад, закриває файлові дескриптори або з'єднання з базою даних.

java
class CalculatorTest {

    private Calculator calculator;

    @BeforeEach
    void setUp() {
        calculator = new Calculator();
    }

    @Test
    void subtractionShouldReturnCorrectResult() {
        int result = calculator.subtract(10, 4);
        assertEquals(6, result);
    }

    @AfterEach
    void tearDown() {
        calculator.reset();
    }
}

Assertions: перевірка результатів у JUnit

Assertions — це статичні методи, які порівнюють фактичний результат з очікуваним та викидають виняток при неспівпадінні. JUnit 5 пропонує клас org.junit.jupiter.api.Assertions з більш ніж 25 методами для різних сценаріїв перевірки — від простого порівняння значень до перевірки таймаутів та групових assertion.

  • assertEquals(expected, actual) — перевіряє рівність через equals().
  • assertTrue(condition) — перевіряє, що умова істинна.
  • assertFalse(condition) — перевіряє, що умова хибна.
  • assertNotNull(object) — перевіряє, що об'єкт не null.
  • assertNull(object) — перевіряє, що об'єкт дорівнює null.
  • assertThrows(exception, executable) — перевіряє, що код викидає вказаний виняток.
  • assertAll(executables) — групує кілька перевірок та виконує всі, не зупиняючись на першій помилці.

assertThrows для перевірки винятків

Окремої уваги заслуговує метод assertThrows, який дозволяє перевірити, що код коректно обробляє помилкові ситуації — ділення на нуль, передачу null, перевищення лімітів.

java
@Test
void divisionByZeroShouldThrowException() {
    Calculator calc = new Calculator();

    ArithmeticException exception = assertThrows(
        ArithmeticException.class,
        () -> calc.divide(10, 0)
    );

    assertEquals("Cannot divide by zero", exception.getMessage());
}

Параметризовані тести в JUnit

Параметризовані тести дозволяють запустити один і той самий тестовий метод з різними наборами аргументів. У JUnit 5 для цього використовується анотація @ParameterizedTest у комбінації з джерелом даних — @ValueSource, @CsvSource, @MethodSource або @EnumSource.

Цей підхід радикально скорочує дублювання коду: замість десяти однакових тестів для різних значень пишеться один параметризований метод. За даними Google Testing Blog, параметризація знижує обсяг тестового коду на 40–60% без втрати покриття.

Приклад з CsvSource

Анотація @CsvSource передає в тест кілька рядків з роздільником-комою. Кожен рядок відповідає одному запуску тесту. JUnit автоматично перетворює рядкові значення в потрібні типи: int, long, String та інші.

java
@ParameterizedTest
@CsvSource({
    "1,    1,   2",
    "2,    3,   5",
    "10,  20,  30",
    "-1,   1,   0"
})
void additionWithMultipleInputs(int a, int b, int expected) {
    assertEquals(expected, a + b);
}

MethodSource для складних об'єктів

Коли вхідні дані складніші за прості числа або рядки, використовується @MethodSource. Він посилається на статичний метод, який повертає Stream аргументів — наприклад, Stream of Arguments або Stream of User об'єктів для тестування DAO-шару.

Інтеграція JUnit з Android-проєктами

В Android-розробці JUnit використовується в парі з AndroidX Test, який надає розширення для тестування Activity, Content Provider та інших компонентів Android. JUnit відповідає за модульні тести (unit tests), що виконуються на JVM без емулятора, а AndroidX Test — за інструментальні тести на пристрої.

Налаштування Gradle

Для підключення JUnit 5 в Android-проєкт достатньо додати залежність org.junit.jupiter:junit-jupiter в build.gradle рівня модуля. Gradle-плагін AGP підтримує запуск JUnit 5 тестів на JVM через стандартний Test Runner.

kotlin
// build.gradle.kts
android {
    testOptions {
        unitTests.isIncludeAndroidResources = true
    }
}

dependencies {
    testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
    testImplementation("androidx.test:core-ktx:1.6.1")
}

Тестування ViewModel за допомогою JUnit

На практиці JUnit найчастіше застосовується для тестування ViewModel та репозиторіїв — шарів, які не потребують Android-контексту або емулятора. Такий тест виконується за мілісекунди і може бути запущений сотні разів без втрати часу.

  • ViewModel — перевірка станів: loading, success, error.
  • Repository — перевірка маппінгу даних та обробки помилок.
  • UseCase — перевірка бізнес-логіки з моками залежностей.

JUnit 4 vs JUnit 5: ключові відмінності

JUnit 5 (Jupiter) — це не просто нова версія, а повністю перероблена платформа, розділена на три модулі: JUnit Platform (запуск тестів на JVM), JUnit Jupiter (API для написання тестів) та JUnit Vintage (зворотна сумісність з JUnit 4). Така модульність дозволяє підключати різні Test Engine — наприклад, Spek для Kotlin або TestNG.

ХарактеристикаJUnit 4JUnit 5
Пакетorg.junitorg.junit.jupiter
Базова анотація@Test (з junit.framework)@Test (з org.junit.jupiter.api)
Before/After@Before, @After, @BeforeClass@BeforeEach, @AfterEach, @BeforeAll
Параметризовані@RunWith(Parameterized.class)@ParameterizedTest + @ValueSource
Розширення@Rule, @ClassRule@ExtendWith, більш гнучкий API
Java minJava 5Java 8+

Міграція з JUnit 4 на JUnit 5 не вимагає переписування всіх тестів — достатньо підключити JUnit Vintage Engine, і старі тести продовжать працювати. Нові тести рекомендується писати на JUnit 5, щоб використовувати розширення, лямбди в assertions та вбудовану підтримку параметризації.

Часті запитання

Чим JUnit відрізняється від Mockito?

JUnit — це фреймворк для написання та запуску тестів, а Mockito — бібліотека для створення mock-об'єктів. Вони використовуються разом: JUnit керує виконанням тесту, а Mockito підміняє залежності тестованого класу.

Чи можна використовувати JUnit 5 в Android-проєктах?

Так, JUnit 5 повністю сумісний з Android-проєктами. Для unit-тестів достатньо додати залежність junit-jupiter в build.gradle. Інструментальні тести, як і раніше, працюють через AndroidX Test Runner.

Який мінімальний набір анотацій потрібен для тесту?

Мінімально достатньо однієї анотації @Test перед методом. Для ініціалізації та очищення рекомендуються @BeforeEach та @AfterEach, але вони не обов'язкові.

Що таке Test Runner в JUnit?

Test Runner — це компонент JUnit, який сканує classpath, знаходить методи з анотацією @Test, створює екземпляри тестових класів та запускає тести. У JUnit 5 цю роль виконує JUnit Platform з підключеними Test Engine.

Як перевірити, що метод викидає виняток?

Використовуйте assertThrows(Class, Executable) — він приймає тип очікуваного винятку та лямбду з викликом методу. JUnit перевіряє, що виняток дійсно було викинуто, і повертає його для додаткової перевірки.

Підсумки

  • JUnit — стандартний фреймворк модульного тестування для Java та Kotlin, основа екосистеми xUnit.
  • Анотації @Test, @BeforeEach, @AfterEach керують життєвим циклом тестового класу.
  • Assertions — assertEquals, assertTrue, assertThrows перевіряють коректність результатів.
  • Параметризовані тести з @CsvSource та @MethodSource скорочують дублювання коду.
  • JUnit 5 — модульна архітектура з платформою, Jupiter API та підтримкою розширень.
  • Android-інтеграція — JUnit працює на JVM через стандартний Test Runner без емулятора.
  • Test Runner автоматично виявляє та запускає @Test-методи, повідомляючи про результати.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також