Parametrisierte Tests in JUnit 5

Parametrisierte Tests in JUnit 5 ermöglichen es uns, einen Test mehrmals mit verschiedenen Argumenten auszuführen. Dafür benutzt man die Annotation @ParameterizedTest an einer Testmethode anstelle der @Test Annotation. Außerdem ist noch mindestens eine Datenquelle zu definieren, die die Argumente für die Testmethode liefert. Zum Definieren von Datenquellen gibt es verschiedene Annotationen.

@CsvSource

Mit der @CsvSource Annotation können Argumentlisten als durch Kommas getrennte Werte (z. B. String-Literale) ausgedrückt werden:

@ParameterizedTest
@CsvSource({
        "JUnit,              5"
        "Java,               8"
        "OIO, Schulung,      60"
})
void checkValuesWithCsvSource (String name, int number) {
    assertNotNull(name);   
}

In diesem Beispiel ist zu sehen, dass die Werte in Anführungszeichen angegeben sind. Wenn mehrere Werte in einem einfachen Anführungszeichen angegeben sind, werden diese Werte als ein einzelnes Argument für eine Position interpretiert (siehe Zeile 3 im nächsten Beispiel).

Mögliche Definitionen der Datenquelle mit @CsvSource und deren Ausgabe:

@CsvSource({"JUnit,   5"})  ->  "JUnit",     "5"
@CsvSource({ "Java,  '' " })  ->  "Java",     ""
@CsvSource({"OIO, 'Schulung, 60'"}) -> "OIO", "Schulung, 60"
@CsvSource({ "JUnit,  " })  ->   "JUnit",   null

Wenn ein einfaches Anführungszeichen keinen Wert enthält, wird es als leere Zeichenfolge interpretiert (Zeile 2), während ein vollständig leerer Wert als Nullreferenz interpretiert wird (Zeile 4).  Des Weiteren wird eine ArgumentConversionException ausgelöst, wenn eine Nullreferenz einem primitiver Typ in der Testmethode übergeben werden soll.

@CsvFileSource

Mit @CsvFileSource können CSV-Dateien aus dem Klassenpfad verwendet werden. Jede Zeile aus einer CSV-Datei führt zu einem Aufruf des parametrisierten Tests.

@ParameterizedTest
@CsvFileSource(resources = "/oio-schulungen.csv")
void checkValuesWithCsvFileSource(String title, double price) {
    assertNotNull(title);
}

@ValueSource

Diese Annotation wird verwendet, um eine einfache Datenquelle zu definieren. Dabei kann ein einzelnes Array von Literalen angegeben werden. Der Test lässt sich dann mit einem einzigen Argument in der Testmethode ausführen.

Folgende Typen von Literalen können mit dieser Annotation verwendet werden: short, byte, int, long, double, char, java.lang.String, java.lang.Class.

@ParameterizedTest
@ValueSource(strings = {"OiO", "Schulung"})
void checkWhiteSpace(String testParam) {
    assertTrue(StringUtils.doesNotContainWhitespace(testparam));
}

Die Testmethode gibt folgendes Ergebnis aus:

@NullSource

Diese Annotation liefert einen Nullwert als Quelle, wenn man eine Methode mit dem Nullwert testen will. Allerdings kann sie für primitive Typen als Parameter nicht verwendet werden.

@EmptySource

Mit der @EmptySource Annotation kann ein leeres Argument als Parameter von den folgenden Typen in einer Testmethode geliefert werden: java.lang.String, java.util.List, java.util.Set, java.util.Map, primitive Arrays(z. B. int[], char[] usw.), Objekt Arrays(z. B. String[], Integer[] [] usw.). Der Test erhält damit die leere Variante des Parametertyps.

@ParameterizedTest
@NullSource
@EmptySource
@ValueSource(strings = {" ", "     ", "\t"})
void checkNullAndEmptyStrings(String text) {
    assertTrue(text == null || text.trim().isEmpty());
}

Dieses Beispiel zeigt eine Testmethode mit Annotationen, die einen Nullwert und einen leeren String zur Verfügung stellen:

@NullAndEmptySource

Die Annotation @NullAndEmptySource ist eine Kombination von oben genannten beiden Annotationen @NullSource und @EmptySource. Somit kann man mit einer Annotation einen Nullwert und ein leeres Argument als Parameter liefern. Folgendes Beispiel zeigt die gleiche oben beschriebene Testmethode mit @NullAndEmptySource und mit dem gleichen Ergebnis:

@DisplayName("Test Using @NullAndEmptySource")
@NullAndEmptySource
@ParameterizedTest
@ValueSource(strings = {" ", "     ", "\t"})
void checkNullAndEmptyStrings(String text) {
    assertTrue(text == null || text.trim().isEmpty());
}

@EnumSource

@EnumSource ermöglicht es, einen Test einmal für jeden Wert einer Enumeration oder Aufzählung auszuführen.

@DisplayName("Test Using @EnumSource")
@ParameterizedTest
@EnumSource(TimeUnit.class)
void checkvaluesFromEnumSource(TimeUnit timeUnit) {
    assertNotNull(timeUnit);
}

Daraus ergeben sich folgende Werte:

@MethodSource

Mithilfe dieser Annotation werden die Argumente für die Testmethode direkt durch eine Methode übergeben, die verschiedene Typen (z. B. Stream, Collection, Iterator oder Iterable usw.) zurückgeben kann.

Im folgenden Beispiel wird eine lokale Methode benutzt, um einen Stream von Strings in die Testmethode zu übergeben:

@ParameterizedTest
@MethodeSource("strings")
void checkvaluesFromMethodeSource(String testParam) {
    assertNotNull(testParam);
}

static Stream<String> strings() {
      return Stream.of("Java", "Angular");
}

Mehr Informationen zum Thema JUnit 5 – Parameterized Tests findet man im JUnit 5 User Guide.

Short URL for this post: https://wp.me/p4nxik-3rr
This entry was posted in Java and Quality and tagged , . Bookmark the permalink.

Leave a Reply