Und das hat einen Grund: Es ist nicht die radikale Neuerfindung, sondern das Release der Modernisierung, Stabilisierung und Vereinheitlichung.
Die Java-Mindestversion wurde von Java 8 auf 17 angehoben, alle Dependencies haben nun die gleiche Versionsnummer, vorhandene Features sind für Entwickler leichter einsetzbar, und überhaupt ist alles runder.
Werfen wir einen Blick auf die wichtigsten Neuerungen.
Java 17 als Mindestvoraussetzung
JUnit 6 setzt mindestens Java 17 voraus, Java 8 wird nicht mehr unterstützt. Java 11 auch nicht. Die Unterstützung für die älteren Java-Versionen wurde komplett entfernt.
Dadurch kann JUnit intern moderne Sprach- und Plattformfeatures nutzen und muss keine Kompatibilitätsschichten für veraltete Java-Versionen mehr mitführen. Für Anwender bedeutet das vor allem: Wer JUnit 6 einsetzen möchte, muss sein Projekt auf Java 17 oder neuer betreiben.
Vereinheitlichte Versionierung
JUnit 6 verwendet für alle Module dieselbe Versionsnummer. Bisher hatten JUnit Platform (1.x) und JUnit Jupiter (5.x) unterschiedliche Versionen. Jetzt läuft alles unter einer einheitlichen Versionsnummer 6.x. Dadurch wird das Dependency Management einfacher, insbesondere in Verbindung mit der JUnit BOM, da alle JUnit-Abhängigkeiten automatisch in einer zueinander passenden Version verwendet werden.
Verbesserte CSV-Unterstützung für parametrisierte Tests
Die alte Bibliothek univocity-parsers, die JUnit bisher für @CsvSource verwendet hat, wird nicht mehr gewartet. JUnit 6 verwendet nun FastCSV. Dadurch werden CSV-Daten schneller und RFC-4180-konform verarbeitet. Mehr Performance, präzisere Fehlermeldungen.
Zusätzlich unterstützt @CsvSource nun Zeichenfolgen als Trennzeichen (delimiterString) sowie Java-Textblöcke, wodurch größere Testdatensätze deutlich lesbarer werden.
public class CsvParameterizedTest {
@ParameterizedTest
@CsvSource(
delimiterString = "::",
textBlock = """
Alice::42
Bob::nineteen
Charlie::35
"""
)
void csv(String name, int age) {
System.out.println(name + " -> " + age);
assertTrue(age > 0);
}
}
Die Ausgabe sieht so aus:

Wie man sieht, schlägt Bob fehl, da „nineteen“ kein gültiger Integer ist. Dank FastCVS ist die Fehlermeldung dabei jetzt noch präziser.
Übersichtlich und einfach nachvollziehbar. Gerade bei umfangreichen parametrisierten Tests verbessert dies die Wartbarkeit und erleichtert die Fehlersuche.
JRE-Bedingungen (JRE Conditions) für Java-Versionen
Mit JRE-Bedingungen können Tests gezielt nur unter bestimmten Java-Versionen oder Versionsbereichen ausgeführt werden. Typische Anwendungsfälle sind Tests für neue Sprach- oder Plattformfeatures, die erst ab einer bestimmten Java-Version verfügbar sind, oder Bibliotheken, die mehrere Java-Versionen unterstützen.
@Test
@EnabledOnJre(JRE.JAVA_17)
void runsOnlyOnJava17() {
System.out.println("✓ Running on Java 17 only");
}
@Test
@EnabledOnJre(JRE.JAVA_25)
void runsOnlyOnJava25() {
System.out.println("✓ Running on Java 25 only");
}
@Test
@DisabledOnJre(JRE.JAVA_25)
void runsOnEverySupportedJavaExcept25() {
System.out.println("✓ Running because this is NOT Java 25");
}
/**
* Typical real-world example: A feature (e.g. Virtual Threads) is available only from Java 21 onwards.
*/
@Test
@EnabledForJreRange(min = JRE.JAVA_21)
void runsOnJava21AndNewer() {
System.out.println("✓ Running on Java 21+");
}
/**
* Example for libraries that officially support a range of Java versions.
*/
@Test
@EnabledForJreRange(
min = JRE.JAVA_17,
max = JRE.JAVA_25
)
void runsFromJava17ThroughJava25() {
System.out.println("✓ Running on Java 17..25");
}
JUnit 6 modernisiert diese API entsprechend der neuen Mindestvoraussetzung Java 17 und entfernt die Unterstützung für nicht mehr unterstützte Java-Versionen.
JSpecify-Integration für Null-Sicherheit
Die öffentlichen APIs von JUnit 6 sind mit JSpecify-Annotationen versehen, die angeben, welche Parameter und Rückgabewerte null sein dürfen und welche nicht. Echte Typsicherheit zur Compilezeit statt NullPointerExceptions zur Laufzeit.
@Test
void validExecutable() {
Executable executable = () -> System.out.println("Hello JUnit 6");
assertDoesNotThrow(executable);
}
@Test
void accidentalNullExecutable() {
// Simulate a bug
Executable executable = null;
// Compiles...
// ...but IntelliJ/Eclipse using JSpecify can warn:
// "Argument 'executable' is marked @NonNull"
assertThrows(RuntimeException.class, executable);
}
Entwicklungsumgebungen und statische Analysewerkzeuge, die JSpecify unterstützen, können dadurch fehlerhafte Verwendungen der JUnit-API bereits während der Entwicklung erkennen. Wird beispielsweise ein null-Wert als Parameter übergeben, der nicht null sein darf, kann die IDE eine Warnung anzeigen.

Der Nutzen hängt davon ab, ob das verwendete Werkzeug JSpecify bereits unterstützt. Am Laufzeitverhalten von Tests ändert sich dadurch nichts.
Und sonst?
JFR-Integration
Früher gab es ein separates Modul (junit-platform-jfr). In JUnit 6 ist die Flight-Recorder-Unterstützung direkt in den Core (junit-platform-launcher) gewandert. Jetzt lässt sich bei der Testausführung (z. B. via Build-Tool oder CI) direkt ein JFR-Recording starten, um Performance-Engpässe oder Speicherprobleme bei großen Test-Suiten zu analysieren.
Cancellation API
Laufende Tests können nun über ein CancellationToken mitten im Run abgebrochen werden. Das kann für CI/CD-Pipelines nützlich sein.
Aufgeräumte Module
Eine Warnung für alle, die von uralten Versionen wechseln möchten: Ein paar alte Zöpfe wurden abgeschnitten. junit-platform-runner wurde ersatzlos gestrichen, junit-platform-jfr ist direkt in den Laucher gewandert (siehe voriger Punkt). Außerdem wurde das Migrationsmodul junit-jupiter-migrationsupport als deprecated markiert.
Entscheidungshilfe: Lohnt sich der Umstieg auf JUnit 6?
Der Umstieg ist kein „Sofort-erledigen!“-Notfall, aber für viele Teams ein logischer nächster Schritt. Hier eine Orientierungshilfe.
Wann der „Umstieg jetzt“ sinnvoll ist
- Das Projekt arbeitet bereits mit Java 17, 21 oder 25 und modernem Tech-Stack. Dann gibt es keinen Grund, nicht auch JUnit auf Version 6 anzuheben.
- Die Build-Dateien wollen endlich mal wieder aufgeräumt werden. Wenn das Versionsdurcheinander der verschiedenen JUnit-Komponenten schon immer gestört hat, bringt JUnit 6 hier endlich Ordnung rein.
Wann „warten“ okay ist
- Das Projekt hängt aus Gründen bei Java 8 oder 11 fest. JUnit 6 setzt mindestens Java 17 voraus, und solange das Hauptprojekt nicht migriert wurde, bleibt man auf JUnit 5, notgedrungen. JUnit 5 ist stabil, gut abgehangen und erhält auch weiterhin Support.
- Es gibt wichtigere Baustellen. Das Projekt läuft auf Java 17+, aber parametrisierte Tests werden kaum angefasst werden und Kotlin-Coroutinen nicht genutzt, dann brächte ein Umstieg zwar Performance- und Lesbarkeitsvorteile im Detail, aber nichts Revolutionäres, für das man alles stehen und liegen lassen muss.
Tipps für den Umstieg
Der Umstieg von JUnit 5 auf 6 ist zwar wie alles, was „mal schnell“ gemacht werden können soll, nicht ohne Aufwand, aber eher als sanftes technisches Upgrade denn einen kompletten und schmerhaften Rewrite zu sehen.
- Offensichtlich, aber trotzem erwähnenswert: Das Projekt muss mindestens auf Java 17 angehoben sein.
- Da JUnit 6 auf die einheitliche Versionierung setzt, können die alten, separaten Versionsvariablen (wie
junit.jupiter.versionvs.junit.platform.version) aus der Build-Konfiguration entfernt werden. Es gibt nur noch eine globale JUnit-Version. - Alte Migrations-Module: Falls das Projekt noch sehr alte JUnit-4-Tests mitschleppt und dafür
junit-jupiter-migrationsupportnutzt, ist jetzt der perfekte Zeitpunkt, diese alten Tests endlich auf JUnit 6-Syntax umzuschreiben. - Immer gern zu hören: Ein schrittweiser Umstieg ist möglich! Da die
@Test-,@BeforeEach– und@AfterEach-Annotationen und deren Verhalten identisch geblieben sind, reicht es in vielen Fällen aus, einfach die Versionsnummer in derpom.xmloderbuild.gradlehochzusetzen.
Fazit
JUnit 6 führt keine grundlegend neue Art des Testens ein. Stattdessen modernisiert das Release die bestehende Plattform:
- Java 17 als zeitgemäße Basis
- Vereinfachtes Dependency Management
- Bessere Unterstützung durch IDEs und statische Analyse
- Lesbarere parametrisierte Tests
- Reproduzierbarere Testausführung
- Bessere Integration in moderne Build- und CI-Prozesse
Der Schwerpunkt liegt damit weniger auf revolutionären Test-Features als auf einer verbesserten Entwicklererfahrung und einer Modernisierung des JUnit-Ökosystems. Wer moderne Projekte pflegt, nimmt das Upgrade einfach beim nächsten Sprint-Wechsel dankend mit.







