Assertions in JUnit 4 und JUnit 5

Zusicherungen in JUnit 4 und JUnit 5

1. Einführung

In diesem Artikel werden wir die in JUnit verfügbaren Aussagen im Detail untersuchen.

Nach den Artikelnmigrating from JUnit 4 to JUnit 5 undA Guide to JUnit 5gehen wir nun auf Details zu den verschiedenen in JUnit 4 und JUnit 5 verfügbaren Behauptungen ein.

Wir werden auch die Verbesserungen hervorheben, die an den Behauptungen mit JUnit 5 vorgenommen wurden.

2. Behauptungen

Assertions are utility methods to support asserting conditions in tests; Auf diese Methoden kann über die KlasseAssertin JUnit 4 und die KlasseAssertionsin JUnit 5 zugegriffen werden.

Um die Lesbarkeit des Tests und der Aussagen selbst zu verbessern, wird immer empfohlen,importtatisch der jeweiligen Klasse zuzuordnen. Auf diese Weise können wir direkt auf die Assertionsmethode selbst verweisen, ohne die darstellende Klasse als Präfix.

Beginnen wir mit der Untersuchung der mit JUnit 4 verfügbaren Behauptungen.

3. Behauptungen in JUnit 4

In dieser Version der Bibliothek sind Zusicherungen für alle primitiven TypenObjects, undarrays (entweder von Primitiven oderObjects). verfügbar

Die Parameterreihenfolge innerhalb der Zusicherung ist der erwartete Wert, gefolgt vom tatsächlichen Wert. Optional kann der erste Parameter eineString-Nachricht sein, die die Nachrichtenausgabe der ausgewerteten Bedingung darstellt.

Es gibt nur einen geringfügigen Unterschied in der Definition derassertThat-Aussagen, aber wir werden später darauf eingehen.

Beginnen wir mit demassertEquals.

3.1. assertEquals

Die Behauptung vonassertEqualsbestätigt, dass der erwartete und der tatsächliche Wert gleich sind:

@Test
public void whenAssertingEquality_thenEqual() {
    String expected = "example";
    String actual = "example";

    assertEquals(expected, actual);
}

Es ist auch möglich, eine Nachricht anzugeben, die angezeigt werden soll, wenn die Zusicherung fehlschlägt:

assertEquals("failure - strings are not equal", expected, actual);

3.2. assertArrayEquals

Wenn wir behaupten wollen, dass zwei Arrays gleich sind, können wirassertArrayEquals: verwenden

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = {'J','u','n','i','t'};
    char[] actual = "Junit".toCharArray();

    assertArrayEquals(expected, actual);
}

Wenn beide Arraysnull sind, werden sie von der Assertion als gleich betrachtet:

@Test
public void givenNullArrays_whenAssertingArraysEquality_thenEqual() {
    int[] expected = null;
    int[] actual = null;

    assertArrayEquals(expected, actual);
}

3.3. assertNotNull undassertNull

Wenn wir testen möchten, ob ein Objektnull ist, können wir die BehauptungassertNull verwenden:

@Test
public void whenAssertingNull_thenTrue() {
    Object car = null;

    assertNull("The car should be null", car);
}

Umgekehrt können wirassertNotNull assertion. verwenden, wenn wir behaupten möchten, dass ein Objekt nicht null sein soll

3.4. assertNotSame undassertSame

MitassertNotSame kann überprüft werden, ob sich zwei Variablen nicht auf dasselbe Objekt beziehen:

@Test
public void whenAssertingNotSameObject_thenDifferent() {
    Object cat = new Object();
    Object dog = new Object();

    assertNotSame(cat, dog);
}

Wenn wir andernfalls überprüfen möchten, ob zwei Variablen auf dasselbe Objekt verweisen, können wir die Zusicherung vonassertSameverwenden.

3.5. assertTrue undassertFalse

Wenn wir überprüfen möchten, ob eine bestimmte Bedingungtrue oderfalse ist, können wir jeweils die BehauptungassertTrue oder die BehauptungassertFalse verwenden:

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue("5 is greater then 4", 5 > 4);
    assertFalse("5 is not greater then 6", 5 > 6);
}

3.6. fail

Die Behauptung vonfail schlägt einen Test fehl, der einAssertionFailedError auslöst. Es kann verwendet werden, um zu überprüfen, ob eine tatsächliche Ausnahme ausgelöst wurde oder wenn ein Test während der Entwicklung fehlschlagen soll.

Mal sehen, wie wir es im ersten Szenario verwenden können:

@Test
public void whenCheckingExceptionMessage_thenEqual() {
    try {
        methodThatShouldThrowException();
        fail("Exception not thrown");
    } catch (UnsupportedOperationException e) {
        assertEquals("Operation Not Supported", e.getMessage());
    }
}

3.7. assertThat

Die Zusicherung vonassertThatist die einzige in JUnit 4, die eine umgekehrte Reihenfolge der Parameter im Vergleich zu den anderen Zusicherungen aufweist.

In diesem Fall enthält die Zusicherung eine optionale Fehlermeldung, den tatsächlichen Wert und einMatcher-Objekt.

Lassen Sie uns sehen, wie wir mit dieser Behauptung prüfen können, ob ein Array bestimmte Werte enthält:

@Test
public void testAssertThatHasItems() {
    assertThat(
      Arrays.asList("Java", "Kotlin", "Scala"),
      hasItems("Java", "Kotlin"));
}

Zusätzliche Informationen zur leistungsstarken Verwendung der Zusicherung vonassertThat mit dem ObjektMatcher finden Sie unterTesting with Hamcrest.

4. JUnit 5 Behauptungen

JUnit 5 behielt viele der Assertionsmethoden von JUnit 4 bei, fügte jedoch einige neue hinzu, die die Java 8-Unterstützung nutzen.

Auch in dieser Version der Bibliothek sind Zusicherungen für alle Grundtypen,Objects, und Arrays (entweder von Grundelementen oder Objekten) verfügbar.

Die Reihenfolge der Parameter der Zusicherungen wurde geändert, und der Ausgabemeldungsparameter wurde als letzter Parameter verschoben. Dank der Unterstützung von Java 8 kann die AusgabenachrichtSupplier betragen, was eine verzögerte Auswertung ermöglicht.

Beginnen wir mit der Überprüfung der Aussagen, die auch in JUnit 4 verfügbar sind.

4.1. assertArrayEquals

Die Behauptung vonassertArrayEqualsbestätigt, dass die erwarteten und die tatsächlichen Arrays gleich sind:

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = { 'J', 'u', 'p', 'i', 't', 'e', 'r' };
    char[] actual = "Jupiter".toCharArray();

    assertArrayEquals(expected, actual, "Arrays should be equal");
}

Wenn die Arrays nicht gleich sind, wird die Meldung "Arrays should be equal" als Ausgabe angezeigt.

4.2. assertEquals

Wenn wir behaupten wollen, dass zweifloatsgleich sind, können wir die einfache Behauptung vonassertEqualsverwenden:

@Test
public void whenAssertingEquality_thenEqual() {
    float square = 2 * 2;
    float rectangle = 2 * 2;

    assertEquals(square, rectangle);
}

Wenn wir jedoch behaupten möchten, dass der tatsächliche Wert um ein vordefiniertes Delta vom erwarteten Wert abweicht, können wir weiterhinassertEquals verwenden, müssen jedoch den Delta-Wert als dritten Parameter übergeben:

@Test
public void whenAssertingEqualityWithDelta_thenEqual() {
    float square = 2 * 2;
    float rectangle = 3 * 2;
    float delta = 2;

    assertEquals(square, rectangle, delta);
}

4.3. assertTrue undassertFalse

Mit der Zusicherung vonassertTrue kann überprüft werden, ob die angegebenen Bedingungentrue sind:

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue(5 > 4, "5 is greater the 4");
    assertTrue(null == null, "null is equal to null");
}

Dank der Unterstützung des Lambda-Ausdrucks ist es möglich, der Behauptung einBooleanSupplier anstelle einerboolean-Bedingung zu liefern.

Mal sehen, wie wir die Richtigkeit vonBooleanSupplier mithilfe derassertFalse-Behauptung bestätigen können:

@Test
public void givenBooleanSupplier_whenAssertingCondition_thenVerified() {
    BooleanSupplier condition = () -> 5 > 6;

    assertFalse(condition, "5 is not greater then 6");
}

4.4. assertNull undassertNotNull

Wenn wir behaupten wollen, dass ein Objekt nichtnull ist, können wir die BehauptungassertNotNull verwenden:

@Test
public void whenAssertingNotNull_thenTrue() {
    Object dog = new Object();

    assertNotNull(dog, () -> "The dog should not be null");
}

Umgekehrt können wir die BehauptungassertNull verwenden, um zu überprüfen, ob die tatsächlichenull ist:

@Test
public void whenAssertingNull_thenTrue() {
    Object cat = null;

    assertNull(cat, () -> "The cat should be null");
}

In beiden Fällen wird die Fehlermeldung verzögert abgerufen, da es sich umSupplierhandelt.

4.5. assertSame undassertNotSame

Wenn wir behaupten wollen, dass sich das Erwartete und das Tatsächliche auf dasselbeObjectbeziehen, müssen wir die Behauptung vonassertSameverwenden:

@Test
public void whenAssertingSameObject_thenSuccessfull() {
    String language = "Java";
    Optional optional = Optional.of(language);

    assertSame(language, optional.get());
}

Umgekehrt können wir dieassertNotSame verwenden.

4.6. fail

Die Zusicherung vonfailbesteht einen Test mit der angegebenen Fehlermeldung sowie der zugrunde liegenden Ursache nicht. Dies kann nützlich sein, um einen Test zu markieren, wenn seine Entwicklung noch nicht abgeschlossen ist:

@Test
public void whenFailingATest_thenFailed() {
    // Test not completed
    fail("FAIL - test not completed");
}

4.7. assertAll

Eine der in JUnit 5 eingeführten neuen Behauptungen istassertAll.

Mit dieser Zusicherung können gruppierte Zusicherungen erstellt werden, in denen alle Zusicherungen ausgeführt und ihre Fehler zusammen gemeldet werden. Im Detail akzeptiert diese Zusicherung eine Überschrift, die in der Nachrichtenzeichenfolge fürMultipleFailureError undStream vonExecutable. enthalten ist

Definieren wir eine gruppierte Behauptung:

@Test
public void givenMultipleAssertion_whenAssertingAll_thenOK() {
    assertAll(
      "heading",
      () -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
      () -> assertEquals("java", "JAVA".toLowerCase()),
      () -> assertEquals(null, null, "null is equal to null")
    );
}

Die Ausführung einer gruppierten Zusicherung wird nur unterbrochen, wenn eine der ausführbaren Dateien eine Ausnahme auf der schwarzen Liste auslöst (z. B.OutOfMemoryError).

4.8. assertIterableEquals

DieassertIterableEquals bestätigen, dass die erwarteten und die tatsächlichen Iterablen zutiefst gleich sind.

Um gleich zu sein, müssen beide iterierbaren Elemente gleiche Elemente in derselben Reihenfolge zurückgeben, und es ist nicht erforderlich, dass die beiden iterierbaren Elemente vom gleichen Typ sind, um gleich zu sein.

Lassen Sie uns anhand dieser Überlegung sehen, wie wir behaupten können, dass zwei Listen unterschiedlicher Typen (z. B.LinkedList undArrayList) gleich sind:

@Test
public void givenTwoLists_whenAssertingIterables_thenEquals() {
    Iterable al = new ArrayList<>(asList("Java", "Junit", "Test"));
    Iterable ll = new LinkedList<>(asList("Java", "Junit", "Test"));

    assertIterableEquals(al, ll);
}

Auf die gleiche Weise wie beiassertArrayEquals werden beide Iterablen als gleich angesehen, wenn sie null sind.

4.9. assertLinesMatch

DieassertLinesMatch bestätigen, dass die erwartete Liste vonString mit der tatsächlichen Liste übereinstimmt.

Diese Methode unterscheidet sich vonassertEquals undassertIterableEquals, da sie für jedes Paar erwarteter und tatsächlicher Linien diesen Algorithmus ausführt:

  1. Überprüfen Sie, ob die erwartete Linie mit der tatsächlichen Linie übereinstimmt. Wenn ja, geht es mit dem nächsten Paar weiter

  2. Behandeln Sie die erwartete Zeile als regulären Ausdruck und führen Sie eine Überprüfung mit der MethodeString.matches() durch. Wenn ja, geht es mit dem nächsten Paar weiter

  3. Überprüfen Sie, ob es sich bei der erwarteten Zeile um eine Schnellvorlaufmarkierung handelt. Wenn ja, wenden Sie den Schnellvorlauf an und wiederholen Sie den Algorithmus ab Schritt 1

Mal sehen, wie wir diese Behauptung verwenden können, um zu behaupten, dass zwei Listen vonStringübereinstimmende Linien haben:

@Test
public void whenAssertingEqualityListOfStrings_thenEqual() {
    List expected = asList("Java", "\\d+", "JUnit");
    List actual = asList("Java", "11", "JUnit");

    assertLinesMatch(expected, actual);
}

4.10. assertNotEquals

Ergänzend zuassertEquals behauptet die BehauptungassertNotEquals, dass der erwartete und der tatsächliche Wert nicht gleich sind:

@Test
public void whenAssertingEquality_thenNotEqual() {
    Integer value = 5; // result of an algorithm

    assertNotEquals(0, value, "The result cannot be 0");
}

Wenn beidenull sind, schlägt die Zusicherung fehl.

4.11. assertThrows

Um die Einfachheit und Lesbarkeit zu erhöhen, ermöglicht uns die Zusicherung des neuenassertThrowseine klare und einfache Möglichkeit, festzustellen, ob eine ausführbare Datei den angegebenen Ausnahmetyp auslöst.

Mal sehen, wie wir eine ausgelöste Ausnahme geltend machen können:

@Test
void whenAssertingException_thenThrown() {
    Throwable exception = assertThrows(
      IllegalArgumentException.class,
      () -> {
          throw new IllegalArgumentException("Exception message");
      }
    );
    assertEquals("Exception message", exception.getMessage());
}

Die Zusicherung schlägt fehl, wenn keine Ausnahme ausgelöst wird oder wenn eine Ausnahme eines anderen Typs ausgelöst wird.

4.12. assertTimeout und assertTimeoutPreemptively

Wenn wir behaupten möchten, dass die Ausführung eines geliefertenExecutable vor einem bestimmtenTimeout endet, können wir die Behauptung vonassertTimeout verwenden:

@Test
public void whenAssertingTimeout_thenNotExceeded() {
    assertTimeout(
      ofSeconds(2),
      () -> {
        // code that requires less then 2 minutes to execute
        Thread.sleep(1000);
      }
    );
}

Mit der Zusicherung vonassertTimeoutwird die angegebene ausführbare Datei jedoch im selben Thread des aufrufenden Codes ausgeführt. Folglich wird die Ausführung des Lieferanten nicht vorzeitig abgebrochen, wenn das Zeitlimit überschritten wird.

Wenn wir sicherstellen möchten, dass die Ausführung der ausführbaren Datei abgebrochen wird, sobald das Zeitlimit überschritten wird, können wir die Zusicherung vonassertTimeoutPreemptivelyverwenden.

Beide Zusicherungen können anstelle vonExecutable, aThrowingSupplier akzeptieren und jeden generischen Codeblock darstellen, der ein Objekt zurückgibt und möglicherweiseThrowable. auslösen kann

5. Fazit

In diesem Lernprogramm wurden alle in JUnit 4 und JUnit 5 verfügbaren Zusicherungen behandelt.

Wir haben kurz auf die Verbesserungen hingewiesen, die in JUnit 5 mit der Einführung neuer Behauptungen und der Unterstützung von Lambdas erzielt wurden.

Wie immer ist der vollständige Quellcode für diesen Artikel inover on GitHub verfügbar.