JUnit: co to jest, kluczowe pojęcia i jak działa

Autor: IT Sectr Opublikowano: 2026-04-08 Czas czytania: 8 min

JUnit — to standardowy framework do testów jednostkowych w ekosystemie Java i Kotlin, używany w rozwoju aplikacji Android do sprawdzania logiki biznesowej na poziomie izolowanych komponentów. Framework dostarcza zestaw adnotacji, metod asercji i Test Runnera do automatycznego wykrywania i wykonywania testów. Według danych JUnit.org, biblioteka pozostaje najpopularniejszym rozwiązaniem do testów jednostkowych w ekosystemie JVM: ponad 70% projektów Java używa JUnit w dowolnej wersji.

Najważniejsze

  • JUnit — framework typu open source do testów jednostkowych kodu Java i Kotlin.
  • Adnotacje — @Test, @BeforeEach, @BeforeAll zarządzają cyklem życia klasy testowej.
  • Asercje — assertEquals, assertTrue, assertThrows sprawdzają oczekiwane wyniki.
  • Testy parametryzowane — pozwalają uruchomić jeden test z różnymi zestawami danych wejściowych.
  • Test Runner — infrastruktura JUnit automatycznie znajduje i uruchamia wszystkie testy w projekcie.

Co to jest JUnit?

JUnit — to framework z otwartym kodem źródłowym do pisania i uruchamiania powtarzalnych testów jednostkowych w języku Java i Kotlin. Należy do ekosystemu xUnit — rodziny frameworków opartych na architekturze Kenta Becka i Ericha Gammy, i jest standardowym narzędziem testowania w Android Studio i IntelliJ IDEA.

Głównym zadaniem JUnit jest wyizolowanie małego fragmentu kodu (metody, klasy) i sprawdzenie jego zachowania w kontrolowanych warunkach. Testy są pisane jako zwykłe klasy Java/Kotlin z adnotacjami, a framework zajmuje się wykrywaniem testów, zarządzaniem ich cyklem życia i zbieraniem statystyk wykonania.

Pierwsza wersja JUnit pojawiła się w 1997 roku i radykalnie zmieniła podejście do programowania, popularyzując praktyki Test-Driven Development (TDD). Obecnie JUnit 5 (Jupiter) to aktualna wersja, w pełni przeprojektowana pod modułową architekturę z obsługą Java 8+ i rozszerzeń.

Jak działa JUnit

Mechanizm wykonania JUnit opiera się na wzorcu Test Runner, który skanuje classpath, znajduje metody z adnotacją @Test, tworzy instancję klasy testowej i uruchamia metody w określonej kolejności. Test Runner zarządza cyklem życia: wywołanie BeforeAll → BeforeEach → Test → AfterEach → AfterAll.

Cykl życia klasy testowej

JUnit opakowuje każdą metodę testową w osobną instancję klasy, co gwarantuje izolację między testami. Oznacza to, że pola klasy nie zachowują stanu między różnymi metodami @Test — każdy test zaczyna się od czystego obiektu.

Podstawowa struktura testu

Najprostszy test w JUnit wygląda jako metoda z adnotacją @Test, wewnątrz której wywoływany jest testowany kod i sprawdzany wynik poprzez asercję. Jeśli asercja nie przechodzi — test jest uznawany za nieudany, a JUnit zgłasza błąd.

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

Test Runner automatycznie znajduje taką metodę, uruchamia ją i informuje o wyniku. Jeśli metoda nie rzuca wyjątku — test jest zaliczony (green). Jeśli asercja nie działa — test pada (red).

Adnotacje JUnit: cykl życia testu

Adnotacje JUnit określają, kiedy i jak powinien być wykonywany kod testowy. W JUnit 5 adnotacje znajdują się w pakiecie org.junit.jupiter.api i obejmują wszystkie etapy: przygotowanie danych, wykonanie testu, czyszczenie zasobów.

AdnotacjaPrzeznaczenieWykonanie
@TestOznacza metodę testowąRaz na wywołanie
@BeforeEachPrzygotowanie przed każdym testemPrzed każdym @Test
@BeforeAllJednorazowa inicjalizacja klasyRaz przed wszystkimi testami
@AfterEachCzyszczenie po każdym teściePo każdym @Test
@AfterAllJednorazowe zakończenie klasyRaz po wszystkich testach
@DisplayNameCzytelna nazwa testuDekoracja

Przykład użycia adnotacji

Rozważmy pełną klasę testową z poprawnym cyklem życia. Metoda setUp tworzy świeżą instancję Calculator przed każdym testem, a tearDown zwalnia zasoby — na przykład zamyka deskryptory plików lub połączenia z bazą danych.

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();
    }
}

Asercje: sprawdzanie wyników w JUnit

Asercje — to statyczne metody, które porównują rzeczywisty wynik z oczekiwanym i rzucają wyjątek w przypadku niezgodności. JUnit 5 oferuje klasę org.junit.jupiter.api.Assertions z ponad 25 metodami dla różnych scenariuszy sprawdzania — od prostego porównania wartości aż do sprawdzania timeoutów i grupowania asercji.

  • assertEquals(expected, actual) — sprawdza równość przez equals().
  • assertTrue(condition) — sprawdza, czy warunek jest prawdziwy.
  • assertFalse(condition) — sprawdza, czy warunek jest fałszywy.
  • assertNotNull(object) — sprawdza, czy obiekt nie jest null.
  • assertNull(object) — sprawdza, czy obiekt jest null.
  • assertThrows(exception, executable) — sprawdza, czy kod rzuca określony wyjątek.
  • assertAll(executables) — grupuje kilka sprawdzeń i wykonuje wszystkie, nie zatrzymując się na pierwszym błędzie.

assertThrows do sprawdzania wyjątków

Szczególnej uwagi zasługuje metoda assertThrows, która pozwala sprawdzić, czy kod poprawnie obsługuje sytuacje błędne — dzielenie przez zero, przekazanie null, przekroczenie limitów.

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

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

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

Testy parametryzowane w JUnit

Testy parametryzowane pozwalają uruchomić tę samą metodę testową z różnymi zestawami argumentów. W JUnit 5 służy do tego adnotacja @ParameterizedTest w kombinacji z źródłem danych — @ValueSource, @CsvSource, @MethodSource lub @EnumSource.

To podejście radykalnie zmniejsza powielanie kodu: zamiast dziesięciu identycznych testów dla różnych wartości pisze się jedną metodę parametryzowaną. Według Google Testing Blog, parametryzacja zmniejsza objętość kodu testowego o 40–60% bez utraty pokrycia.

Przykład z CsvSource

Adnotacja @CsvSource przekazuje do testu kilka wierszy z separatorem przecinkowym. Każdy wiersz odpowiada jednemu uruchomieniu testu. JUnit automatycznie konwertuje wartości łańcuchowe na odpowiednie typy: int, long, String i inne.

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 dla złożonych obiektów

Gdy dane wejściowe są bardziej złożone niż proste liczby czy łańcuchy, używa się @MethodSource. Odwołuje się on do statycznej metody, która zwraca Stream argumentów — na przykład Stream of Arguments lub Stream of User obiektów do testowania warstwy DAO.

Integracja JUnit z projektami Android

W rozwoju aplikacji Android JUnit jest używany w parze z AndroidX Test, który dostarcza rozszerzenia do testowania Activity, Content Provider i innych komponentów Androida. JUnit odpowiada za testy jednostkowe (unit tests) wykonywane na JVM bez emulatora, a AndroidX Test za testy instrumentalne na urządzeniu.

Konfiguracja Gradle

Aby podłączyć JUnit 5 w projekcie Android, wystarczy dodać zależność org.junit.jupiter:junit-jupiter w build.gradle poziomu modułu. Wtyczka Gradle AGP obsługuje uruchamianie testów JUnit 5 na JVM przez standardowy 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")
}

Testowanie ViewModel za pomocą JUnit

W praktyce JUnit najczęściej stosuje się do testowania ViewModel i repozytoriów — warstw, które nie wymagają kontekstu Androida ani emulatora. Taki test wykonuje się w milisekundach i może być uruchamiany setki razy bez straty czasu.

  • ViewModel — sprawdzanie stanów: loading, success, error.
  • Repository — sprawdzanie mapowania danych i obsługi błędów.
  • UseCase — sprawdzanie logiki biznesowej z mockami zależności.

JUnit 4 vs JUnit 5: kluczowe różnice

JUnit 5 (Jupiter) — to nie tylko nowa wersja, ale w pełni przeprojektowana platforma podzielona na trzy moduły: JUnit Platform (uruchamianie testów na JVM), JUnit Jupiter (API do pisania testów) i JUnit Vintage (wsteczna zgodność z JUnit 4). Taka modułowość pozwala podłączać różne silniki testowe — na przykład Spek dla Kotlin lub TestNG.

CharakterystykaJUnit 4JUnit 5
Pakietorg.junitorg.junit.jupiter
Podstawowa adnotacja@Test (z junit.framework)@Test (z org.junit.jupiter.api)
Before/After@Before, @After, @BeforeClass@BeforeEach, @AfterEach, @BeforeAll
Parameterized@RunWith(Parameterized.class)@ParameterizedTest + @ValueSource
Extension@Rule, @ClassRule@ExtendWith, bardziej elastyczne API
Java minJava 5Java 8+

Migracja z JUnit 4 na JUnit 5 nie wymaga przepisywania wszystkich testów — wystarczy podłączyć JUnit Vintage Engine, a stare testy będą dalej działać. Nowe testy zaleca się pisać w JUnit 5, aby korzystać z rozszerzeń, lambd w asercjach i wbudowanej obsługi parametryzacji.

Często zadawane pytania

Czym różni się JUnit od Mockito?

JUnit — to framework do pisania i uruchamiania testów, a Mockito — biblioteka do tworzenia obiektów mock. Są używane razem: JUnit zarządza wykonaniem testu, a Mockito podmienia zależności testowanej klasy.

Czy można używać JUnit 5 w projektach Android?

Tak, JUnit 5 jest w pełni zgodny z projektami Android. Do testów jednostkowych wystarczy dodać zależność junit-jupiter w build.gradle. Testy instrumentalne nadal działają przez AndroidX Test Runner.

Jaki minimalny zestaw adnotacji jest potrzebny do testu?

Minimalnie wystarczy jedna adnotacja @Test przed metodą. Do inicjalizacji i czyszczenia zaleca się @BeforeEach i @AfterEach, ale nie są one obowiązkowe.

Czym jest Test Runner w JUnit?

Test Runner — to komponent JUnit, który skanuje classpath, znajduje metody z adnotacją @Test, tworzy instancje klas testowych i uruchamia testy. W JUnit 5 tę rolę pełni JUnit Platform z podłączonymi silnikami testowymi.

Jak sprawdzić, czy metoda rzuca wyjątek?

Użyj assertThrows(Class, Executable) — przyjmuje typ oczekiwanego wyjątku i lambdę z wywołaniem metody. JUnit sprawdza, czy wyjątek rzeczywiście został rzucony, i zwraca go do dodatkowej weryfikacji.

Podsumowanie

  • JUnit — standardowy framework testów jednostkowych dla Java i Kotlin, podstawa ekosystemu xUnit.
  • Adnotacje @Test, @BeforeEach, @AfterEach zarządzają cyklem życia klasy testowej.
  • Asercje — assertEquals, assertTrue, assertThrows sprawdzają poprawność wyników.
  • Testy parametryzowane z @CsvSource i @MethodSource zmniejszają powielanie kodu.
  • JUnit 5 — modułowa architektura z platformą, Jupiter API i obsługą rozszerzeń.
  • Integracja z Androidem — JUnit działa na JVM przez standardowy Test Runner bez emulatora.
  • Test Runner automatycznie wykrywa i uruchamia metody @Test, raportując wyniki.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również