Migration von JUnit 4 zu JUnit 5

Migration von JUnit 4 nach JUnit 5

1. Überblick

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 Artikelhere.

2. JUnit 5 Vorteile

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

  • Das gesamte Framework befand sich in einer einzigen Glasbibliothek. Die gesamte Bibliothek muss importiert werden, auch wenn nur eine bestimmte Funktion erforderlich ist. In JUnit 5, we get more granularity and can import only what is necessary

  • Ein Testläufer kann jeweils nur Tests in JUnit 4 ausführen (z. SpringJUnit4ClassRunner oderParameterized). JUnit 5 allows multiple runners to work simultaneously

  • JUnit 4 ist nie über Java 7 hinausgegangen und verfügt nicht über viele Funktionen von Java 8. JUnit 5 makes good use of Java 8 features

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

3. Unterschiede

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

  • JUnit Platform – Dieses Modul umfasst alle Erweiterungsframeworks, die für die Testausführung, -ermittlung und -berichterstattung 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 den Anmerkungen. The most important one is that we can no longer use @Test annotation for specifying expectations.

Der Parameterexpected in JUnit 4:

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

Jetzt können wir eine MethodeassertThrows verwenden:

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

Dastimeout-Attribut in JUnit 4:

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

Nun dieassertTimeout-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:

  • Die Annotation von@Before wird in@BeforeEach umbenannt

  • Die Annotation von@After wird in@AfterEach umbenannt

  • Die Annotation von@BeforeClass wird in@BeforeAll umbenannt

  • Die Annotation von@AfterClass wird in@AfterAll umbenannt

  • Die Annotation von@Ignore wird in@Disabled umbenannt

3.2. Behauptungen

Wir können jetzt Assertionsnachrichten in einem Lambda in JUnit 5 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 auch Zusicherungen 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 KlasseAssumptions ist jetzt inorg.junit.jupiter.api.Assumptions. JUnit 5 unterstützt die in JUnit 4 vorhandenen Annahmemethoden vollständig und fügt außerdem eine Reihe neuer Methoden hinzu, mit denen einige Zusicherungen nur in 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@Categorygruppieren. Mit JUnit 5 wird die Annotation von@Categorydurch die Annotation von@Tagersetzt:

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

Wir können bestimmte Tags mitmaven-surefire-plugin ein- / ausschließen:


    
        
            maven-surefire-plugin
            
                
                    junit5
                
            
        
    

3.5. Neue Anmerkungen zum Ausführen von Tests

Die@RunWith wurden verwendet, um den Testkontext in andere Frameworks zu integrieren oder den gesamten Ausführungsfluss in den Testfällen in JUnit 4 zu ändern.

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

So verwenden Sie beispielsweise die 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. Anmerkungen zu neuen Testregeln

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

In JUnit 5. Wir können dieselbe Logik mit der Annotation@ExtendWithreproduzieren.

Angenommen, wir haben in JUnit 4 eine benutzerdefinierte Regel zum Schreiben von Protokollspuren vor und nach einem 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
                ...
            }
        };
    }
}

Und wir implementieren es in einer Testsuite:

@Rule
public TraceUnitTestRule traceRuleTests = new TraceUnitTestRule();

In JUnit 5 können wir dasselbe viel intuitiver schreiben:

public class TraceUnitExtension implements AfterEachCallback, BeforeEachCallback {

    @Override
    public void beforeEach(TestExtensionContext context) throws Exception {
        // ...
    }

    @Override
    public void afterEach(TestExtensionContext context) throws Exception {
        // ...
    }
}

Mit denAfterEachCallback undBeforeEachCallback-Schnittstellen von JUnit 5, die im Paketorg.junit.jupiter.api.extension, verfügbar sind, können wir diese Regel problemlos in die Testsuite implementieren:

@RunWith(JUnitPlatform.class)
@ExtendWith(TraceUnitExtension.class)
public class RuleExampleTest {

    @Test
    public void whenTracingTests() {
        /*...*/
    }
}

3.7. JUnit 5 Vintage

JUnit Vintage unterstützt die Migration von JUnit-Tests, indem JUnit 3- oder JUnit 4-Tests im JUnit 5-Kontext ausgeführt werden.

Wir können es verwenden, indem wir die JUnit Vintage Engine importieren:


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

4. Fazit

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 angedeutet, wie Sie von einer Version zur anderen migrieren können.

Die vollständige Implementierung dieses Tutorials finden Sie inover on GitHub.