Migration von JUnit 4 zu JUnit 5

1. Übersicht

In diesem Artikel erfahren Sie, wie Sie von JUnit 4 auf die neueste Version von JUnit 5 migrieren können - mit einem Überblick über die Unterschiede zwischen den beiden Versionen der Bibliothek.

Die allgemeinen Richtlinien zur Verwendung von JUnit 5 finden Sie in unserem Artikel hier.

2. JUnit 5 Vorteile

Beginnen wir mit der vorherigen Version - JUnit 4 weist einige klare Einschränkungen auf:

  • Das gesamte Framework war in einer einzigen JAR-Bibliothek enthalten. Die gesamte Bibliothek muss importiert werden, auch wenn nur eine bestimmte Funktion erforderlich ist. In JUnit 5 erhalten wir mehr Granularität und können nur das importieren, was erforderlich ist
  • Ein Testläufer kann jeweils nur Tests in JUnit 4 ausführen (z. B. SpringJUnit4ClassRunner oder Parameterized ). Mit JUnit 5 können mehrere Läufer gleichzeitig arbeiten
  • JUnit 4 ist nie über Java 7 hinaus fortgeschritten und hat viele Funktionen von Java 8 verpasst. JUnit 5 nutzt Java 8-Funktionen gut

Die Idee hinter JUnit 5 war, JUnit 4 komplett neu zu schreiben, um die meisten dieser Nachteile zu lösen.

3. Unterschiede

JUnit 4 wurde in Module unterteilt, die JUnit 5 umfassen:

  • JUnit Platform - Dieses Modul umfasst alle Erweiterungsframeworks, die für die Ausführung, Ermittlung und Berichterstellung von Tests von Interesse sein könnten
  • JUnit Vintage - Dieses Modul ermöglicht die Abwärtskompatibilität mit JUnit 4 oder sogar JUnit 3

3.1. Anmerkungen

JUnit 5 enthält wichtige Änderungen in seinen Anmerkungen. Das Wichtigste ist, dass wir die @ Test- Annotation nicht mehr zum Festlegen von Erwartungen verwenden können.

Der erwartete Parameter in JUnit 4:

@Test(expected = Exception.class) public void shouldRaiseAnException() throws Exception { // ... }

Jetzt können wir eine Methode assertThrows verwenden :

public void shouldRaiseAnException() throws Exception { Assertions.assertThrows(Exception.class, () -> { //... }); }

Das Timeout- Attribut in JUnit 4:

@Test(timeout = 1) public void shouldFailBecauseTimeout() throws InterruptedException { Thread.sleep(10); }

Nun die assertTimeout- Methode in JUnit 5:

@Test public void shouldFailBecauseTimeout() throws InterruptedException { Assertions.assertTimeout(Duration.ofMillis(1), () -> Thread.sleep(10)); }

Andere Anmerkungen, die in JUnit 5 geändert wurden:

  • @Before Annotation wird in @BeforeEach umbenannt
  • @After Annotation wird in @AfterEach umbenannt
  • Die Annotation @BeforeClass wird in @BeforeAll umbenannt
  • Die Annotation @AfterClass wird in @AfterAll umbenannt
  • Die Annotation @Ignore wird in @Disabled umbenannt

3.2. Behauptungen

In JUnit 5 können wir jetzt Assertionsnachrichten in ein Lambda schreiben, sodass die verzögerte Auswertung die komplexe Nachrichtenkonstruktion überspringen kann, bis sie benötigt wird:

@Test public void shouldFailBecauseTheNumbersAreNotEqual_lazyEvaluation() { Assertions.assertTrue( 2 == 3, () -> "Numbers " + 2 + " and " + 3 + " are not equal!"); }

Wir können Behauptungen auch in JUnit 5 gruppieren:

@Test public void shouldAssertAllTheGroup() { List list = Arrays.asList(1, 2, 4); Assertions.assertAll("List is not incremental", () -> Assertions.assertEquals(list.get(0).intValue(), 1), () -> Assertions.assertEquals(list.get(1).intValue(), 2), () -> Assertions.assertEquals(list.get(2).intValue(), 3)); }

3.3. Annahmen

Die neue Assumptions- Klasse befindet sich jetzt in org.junit.jupiter.api.Assumptions . JUnit 5 unterstützt die in JUnit 4 vorhandenen Annahmemethoden vollständig und fügt eine Reihe neuer Methoden hinzu, mit denen einige Zusicherungen nur unter bestimmten Szenarien ausgeführt werden können:

@Test public void whenEnvironmentIsWeb_thenUrlsShouldStartWithHttp() { assumingThat("WEB".equals(System.getenv("ENV")), () -> { assertTrue("http".startsWith(address)); }); }

3.4. Markieren und Filtern

In JUnit 4 konnten wir Tests mithilfe der Annotation @Category gruppieren . Bei JUnit 5 wird die Annotation @Category durch die Annotation @Tag ersetzt :

@Tag("annotations") @Tag("junit5") @RunWith(JUnitPlatform.class) public class AnnotationTestExampleTest { /*...*/ }

Wir können bestimmte Tags mit dem Maven-Surefire-Plugin ein- / ausschließen :

   maven-surefire-plugin   junit5     

3.5. Neue Anmerkungen zum Ausführen von Tests

Mit @RunWith wurde der Testkontext in andere Frameworks integriert oder der gesamte Ausführungsablauf in den Testfällen in JUnit 4 geändert.

Mit JUnit 5 können wir jetzt die Annotation @ExtendWith verwenden , um ähnliche Funktionen bereitzustellen.

Beispiel für die Verwendung der Spring-Funktionen in JUnit 4:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( {"/app-config.xml", "/test-data-access-config.xml"}) public class SpringExtensionTest { /*...*/ }

In JUnit 5 ist dies eine einfache Erweiterung:

@ExtendWith(SpringExtension.class) @ContextConfiguration( { "/app-config.xml", "/test-data-access-config.xml" }) public class SpringExtensionTest { /*...*/ } 

3.6. Neue Anmerkungen zu Testregeln

In JUnit 4 wurden die Annotationen @Rule und @ ClassRule verwendet, um Tests besondere Funktionen hinzuzufügen.

In JUnit 5. können wir dieselbe Logik mithilfe der Annotation @ExtendWith reproduzieren .

For example, say we have a custom rule in JUnit 4 to write log traces before and after a test:

public class TraceUnitTestRule implements TestRule { @Override public Statement apply(Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { // Before and after an evaluation tracing here ... } }; } }

And we implement it in a test suite:

@Rule public TraceUnitTestRule traceRuleTests = new TraceUnitTestRule(); 

In JUnit 5, we can write the same in a much more intuitive manner:

public class TraceUnitExtension implements AfterEachCallback, BeforeEachCallback { @Override public void beforeEach(TestExtensionContext context) throws Exception { // ... } @Override public void afterEach(TestExtensionContext context) throws Exception { // ... } }

Using JUnit 5's AfterEachCallback and BeforeEachCallback interfaces available in the package org.junit.jupiter.api.extension, we easily implement this rule in the test suite:

@RunWith(JUnitPlatform.class) @ExtendWith(TraceUnitExtension.class) public class RuleExampleTest { @Test public void whenTracingTests() { /*...*/ } }

3.7. JUnit 5 Vintage

JUnit Vintage aids in the migration of JUnit tests by running JUnit 3 or JUnit 4 tests within the JUnit 5 context.

We can use it by importing the JUnit Vintage Engine:

 org.junit.vintage junit-vintage-engine ${junit5.vintage.version} test 

4. Conclusion

Wie wir in diesem Artikel gesehen haben, ist JUnit 5 eine modulare und moderne Version des JUnit 4-Frameworks. Wir haben die Hauptunterschiede zwischen diesen beiden Versionen vorgestellt und Hinweise zur Migration von einer zur anderen gegeben.

Die vollständige Implementierung dieses Tutorials finden Sie auf GitHub.