JUnit ist ein Standard-Framework für Unit-Tests im Java- und Kotlin-Ökosystem, das in der Android-Entwicklung verwendet wird, um Geschäftslogik auf der Ebene isolierter Komponenten zu überprüfen. Das Framework bietet eine Reihe von Annotationen, Assertion-Methoden und einen Test Runner zur automatischen Erkennung und Ausführung von Tests. Laut JUnit.org bleibt die Bibliothek die beliebteste Lösung für Unit-Tests im JVM-Ökosystem: mehr als 70% der Java-Projekte verwenden JUnit in irgendeiner Version.
Wichtigste Erkenntnisse
JUnit ist ein Open-Source-Framework zum Schreiben und Ausführen wiederholbarer Unit-Tests in Java und Kotlin. Es ist Teil des xUnit-Ökosystems — einer Familie von Frameworks, die auf der Architektur von Kent Beck und Erich Gamma basieren — und das Standard-Testwerkzeug in Android Studio und IntelliJ IDEA.
Die Hauptaufgabe von JUnit besteht darin, ein kleines Codefragment (Methode, Klasse) zu isolieren und sein Verhalten unter kontrollierten Bedingungen zu überprüfen. Tests werden als normale Java-/Kotlin-Klassen mit Annotationen geschrieben, und das Framework übernimmt die Erkennung von Tests, die Lebenszyklusverwaltung und die Sammlung von Ausführungsstatistiken.
Die erste Version von JUnit erschien im Jahr 1997 und veränderte den Entwicklungsansatz radikal, indem sie die Praktiken der testgetriebenen Entwicklung (TDD) populär machte. Heute ist JUnit 5 (Jupiter) die aktuelle Version, die mit einer modularen Architektur, die Java 8+ und Erweiterungen unterstützt, komplett überarbeitet wurde.
Der Mechanismus der JUnit-Ausführung basiert auf dem Test Runner-Muster, das den Classpath scannt, Methoden mit der @Test-Annotation findet, eine Instanz der Testklasse erstellt und die Methoden in einer bestimmten Reihenfolge ausführt. Der Test Runner verwaltet den Lebenszyklus: BeforeAll → BeforeEach → Test → AfterEach → AfterAll.
JUnit kapselt jede Testmethode in eine separate Klasseninstanz und gewährleistet so die Isolation zwischen den Tests. Dies bedeutet, dass Klassenfelder keinen Zustand zwischen verschiedenen @Test-Methoden behalten — jeder Test beginnt mit einem sauberen Objekt.
Der einfachste Test in JUnit ist eine Methode mit der @Test-Annotation, die den zu testenden Code aufruft und das Ergebnis mit einer Assertion überprüft. Wenn die Assertion fehlschlägt, gilt der Test als fehlgeschlagen und JUnit meldet den Fehler.
@Test
void additionShouldReturnCorrectSum() {
var calculator = new Calculator();
var result = calculator.add(2, 3);
assertEquals(5, result);
}
Der Test Runner findet eine solche Methode automatisch, führt sie aus und meldet das Ergebnis. Wenn die Methode keine Ausnahme auslöst — besteht der Test (green). Wenn eine Assertion fehlschlägt — fällt der Test durch (red).
Annotationen in JUnit legen fest, wann und wie der Testcode ausgeführt werden soll. In JUnit 5 befinden sich die Annotationen im Paket org.junit.jupiter.api und decken alle Phasen ab: Datenvorbereitung, Testausführung, Ressourcenbereinigung.
| Annotation | Zweck | Ausführung |
|---|---|---|
| @Test | Markiert eine Testmethode | Einmal pro Aufruf |
| @BeforeEach | Vorbereitung vor jedem Test | Vor jedem @Test |
| @BeforeAll | Einmalige Klasseninitialisierung | Einmal vor allen Tests |
| @AfterEach | Bereinigung nach jedem Test | Nach jedem @Test |
| @AfterAll | Einmaliger Klassenabschluss | Einmal nach allen Tests |
| @DisplayName | Lesbarer Testname | Dekoration |
Betrachten wir eine vollständige Testklasse mit einem korrekten Lebenszyklus. Die Methode setUp erstellt vor jedem Test eine neue Calculator-Instanz, und tearDown gibt Ressourcen frei — zum Beispiel das Schließen von Dateideskriptoren oder Datenbankverbindungen.
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 sind statische Methoden, die das tatsächliche Ergebnis mit dem erwarteten vergleichen und eine Ausnahme auslösen, wenn sie nicht übereinstimmen. JUnit 5 bietet die Klasse org.junit.jupiter.api.Assertions mit über 25 Methoden für verschiedene Überprüfungsszenarien — vom einfachen Wertevergleich bis zu Timeout-Prüfungen und gruppierten Assertions.
Besondere Aufmerksamkeit verdient die Methode assertThrows, mit der überprüft werden kann, ob Code Fehlersituationen — Division durch Null, Übergabe von null, Überschreitung von Grenzen — korrekt behandelt.
@Test
void divisionByZeroShouldThrowException() {
Calculator calc = new Calculator();
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> calc.divide(10, 0)
);
assertEquals("Cannot divide by zero", exception.getMessage());
}
Parametrisierte Tests ermöglichen es, dieselbe Testmethode mit verschiedenen Argumentsätzen auszuführen. In JUnit 5 geschieht dies mit der Annotation @ParameterizedTest in Kombination mit einer Datenquelle — @ValueSource, @CsvSource, @MethodSource oder @EnumSource.
Dieser Ansatz reduziert Code-Duplizierung radikal: Statt zehn identischer Tests für verschiedene Werte wird eine parametrisierte Methode geschrieben. Laut Google Testing Blog reduziert die Parametrisierung das Testcodevolumen um 40–60%, ohne die Abdeckung zu verlieren.
Die Annotation @CsvSource übergibt mehrere kommagetrennte Zeilen an den Test. Jede Zeile entspricht einem Testdurchlauf. JUnit konvertiert automatisch String-Werte in die erforderlichen Typen: int, long, String und andere.
@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);
}
Wenn die Eingabedaten komplexer als einfache Zahlen oder Strings sind, wird @MethodSource verwendet. Es verweist auf eine statische Methode, die einen Stream von Argumenten zurückgibt — zum Beispiel einen Stream von Arguments oder einen Stream von User-Objekten zum Testen der DAO-Ebene.
In der Android-Entwicklung wird JUnit zusammen mit AndroidX Test verwendet, das Erweiterungen zum Testen von Activity, Content Provider und anderen Android-Komponenten bietet. JUnit übernimmt Unit-Tests, die auf der JVM ohne Emulator ausgeführt werden, während AndroidX Test instrumentierte Tests auf dem Gerät übernimmt.
Um JUnit 5 zu einem Android-Projekt hinzuzufügen, genügt es, die Abhängigkeit org.junit.jupiter:junit-jupiter in die build.gradle auf Modulebene aufzunehmen. Das AGP Gradle-Plugin unterstützt die Ausführung von JUnit 5-Tests auf der JVM über den Standard-Test Runner.
// 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")
}
In der Praxis wird JUnit am häufigsten zum Testen von ViewModel und Repositories verwendet — Schichten, die keinen Android-Kontext oder Emulator benötigen. Ein solcher Test wird in Millisekunden ausgeführt und kann hunderte Male ohne Zeitverlust ausgeführt werden.
JUnit 5 (Jupiter) ist nicht nur eine neue Version, sondern eine komplett überarbeitete Plattform, die in drei Module unterteilt ist: JUnit Platform (Testausführung auf der JVM), JUnit Jupiter (API zum Schreiben von Tests) und JUnit Vintage (Rückwärtskompatibilität mit JUnit 4). Diese Modularität ermöglicht den Anschluss verschiedener Test Engines — zum Beispiel Spek für Kotlin oder TestNG.
| Merkmal | JUnit 4 | JUnit 5 |
|---|---|---|
| Paket | org.junit | org.junit.jupiter |
| Basis-Annotation | @Test (aus junit.framework) | @Test (aus org.junit.jupiter.api) |
| Before/After | @Before, @After, @BeforeClass | @BeforeEach, @AfterEach, @BeforeAll |
| Parametrisiert | @RunWith(Parameterized.class) | @ParameterizedTest + @ValueSource |
| Erweiterung | @Rule, @ClassRule | @ExtendWith, flexiblere API |
| Java min | Java 5 | Java 8+ |
Die Migration von JUnit 4 zu JUnit 5 erfordert kein Umschreiben aller Tests — fügen Sie einfach JUnit Vintage Engine hinzu, und alte Tests funktionieren weiterhin. Neue Tests sollten mit JUnit 5 geschrieben werden, um Erweiterungen, Lambda-Assertions und die integrierte Parametrisierungs-Unterstützung zu nutzen.
Häufig gestellte Fragen
JUnit ist ein Framework zum Schreiben und Ausführen von Tests, während Mockito eine Bibliothek zum Erstellen von Mock-Objekten ist. Sie werden zusammen verwendet: JUnit verwaltet die Testausführung, und Mockito ersetzt Abhängigkeiten der zu testenden Klasse.
Ja, JUnit 5 ist vollständig mit Android-Projekten kompatibel. Für Unit-Tests genügt es, die Abhängigkeit junit-jupiter in build.gradle hinzuzufügen. Instrumentierte Tests funktionieren weiterhin über den AndroidX Test Runner.
Minimum ist eine einzige @Test-Annotation vor der Methode. Für Initialisierung und Bereinigung werden @BeforeEach und @AfterEach empfohlen, sind aber nicht obligatorisch.
Der Test Runner ist eine JUnit-Komponente, die den Classpath scannt, Methoden mit der @Test-Annotation findet, Instanzen von Testklassen erstellt und die Tests ausführt. In JUnit 5 wird diese Rolle von der JUnit Platform mit angeschlossenen Test Engines übernommen.
Verwenden Sie assertThrows(Class, Executable) — es akzeptiert den erwarteten Ausnahmetyp und ein Lambda mit dem Methodenaufruf. JUnit überprüft, ob die Ausnahme tatsächlich ausgelöst wurde, und gibt sie zur weiteren Inspektion zurück.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch