JUnit 5 Tutorial:Assertionen mit AssertJ schreiben
Dieser Blogbeitrag beschreibt, wie wir Assertionen mit AssertJ schreiben können. Nachdem wir diesen Blogbeitrag fertiggestellt haben, werden wir:
- Kann die erforderlichen Abhängigkeiten mit Maven und Gradle erhalten.
- Wissen, wie wir grundlegende Behauptungen mit AssertJ schreiben können.
- Verstehen Sie, wie wir die Fehlermeldung anpassen können, die angezeigt wird, wenn eine Assertion fehlschlägt.
- Kann weiche Behauptungen mit AssertJ schreiben.
Fangen wir an.
Erforderliche Abhängigkeiten abrufen
Bevor wir Assertionen mit AssertJ schreiben können, müssen wir sicherstellen, dass die assertj-core
Abhängigkeit (Version 3.21.0) wird im Klassenpfad gefunden.
Wenn wir Maven verwenden, müssen wir den assertj-core
hinzufügen Abhängigkeit zum test
Umfang. Wir können dies tun, indem wir das folgende Snippet zu dependencies
hinzufügen Abschnitt unserer pom.xml Datei:
<dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.21.0</version> <scope>test</scope> </dependency>
Wenn wir Gradle verwenden, müssen wir den assertj-core
hinzufügen Abhängigkeit zum testImplementation
Abhängigkeitskonfiguration. Wir können dies tun, indem wir das folgende Snippet zu unserem build.gradle hinzufügen Datei:
dependencies { testImplementation( 'org.assertj:assertj-core:3.21.0' ) }
Nachdem wir diese Abhängigkeit zum Klassenpfad hinzugefügt haben, können wir Asserts mit AssertJ schreiben. Lassen Sie uns herausfinden, wie wir es tun können.
Aussagen mit AssertJ schreiben
Wenn wir Behauptungen mit AssertJ schreiben wollen, müssen wir den static assertThat()
verwenden Methode des org.assertj.core.api.Assertions
Klasse. Wenn wir diese Methode aufrufen, müssen wir diese zwei Dinge wissen:
- Der
assertThat()
Die Methode nimmt den tatsächlichen Wert oder das Objekt als Methodenparameter. - Der
Assertions()
-Klasse verwendet Methodenüberladung und den Typ des vonassertThat()
zurückgegebenen Objekts Methode hängt vom Typ des Arguments ab, das an diese Methode übergeben wird.
Nachdem wir den assertThat()
aufgerufen haben -Methode können wir unsere Zusicherungen schreiben, indem wir das zurückgegebene Zusicherungsobjekt verwenden. Da AssertJ außerdem eine fließende API bereitstellt, gibt jede Assertionsmethode eine Referenz auf das verwendete Assertionsobjekt zurück. Das bedeutet, dass wir Behauptungen verketten können, indem wir einfach eine andere Behauptungsmethode aufrufen.
Als nächstes werfen wir einen Blick auf einige Beispiele, die zeigen, wie wir Asserts mit AssertJ schreiben können.
Boolesche Werte bestätigen
Wenn wir überprüfen möchten, ob ein boolean
Wert ist true
, müssen wir unsere Assertion schreiben, indem wir isTrue()
aufrufen Methode des AbstractBooleanAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Write assertions for booleans") class BooleanAssertionTest { @Nested @DisplayName("When boolean is true") class WhenBooleanIsTrue { @Test @DisplayName("Should be true") void shouldBeTrue() { assertThat(true).isTrue(); } } }
Wenn wir überprüfen möchten, ob ein boolean
Wert ist false
, müssen wir unsere Assertion schreiben, indem wir isFalse()
aufrufen Methode des AbstractBooleanAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Write assertions for booleans") class BooleanAssertionTest { @Nested @DisplayName("When boolean is false") class WhenBooleanIsFalse { @Test @DisplayName("Should be false") void shouldBeFalse() { assertThat(false).isFalse(); } } }
Lassen Sie uns weitermachen und herausfinden, wie wir überprüfen können, ob ein Objekt null
ist oder ist nicht null
.
Behaupten, dass ein Objekt Null ist oder nicht Null ist
Wenn wir überprüfen möchten, ob ein Objekt null
ist , müssen wir unsere Assertion schreiben, indem wir isNull()
aufrufen Methode des AbstractAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for objects") class ObjectAssertionTest { @Nested @DisplayName("When object is null") class WhenObjectIsNull { private final Object NULL = null; @Test @DisplayName("Should be null") void shouldBeNull() { assertThat(NULL).isNull(); } } }
Wenn wir überprüfen möchten, ob ein Objekt nicht null
ist , müssen wir unsere Assertion schreiben, indem wir isNotNull()
aufrufen Methode des AbstractAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for objects") class ObjectAssertionTest { @Nested @DisplayName("When object is not null") class WhenObjectIsNotNotNull { @Test @DisplayName("Should not be null") void shouldNotBeNull() { assertThat(new Object()).isNotNull(); } } }
Als nächstes werden wir herausfinden, wie wir überprüfen können, ob zwei Objekte (oder Werte) gleich oder ungleich sind.
Behaupten, dass zwei Objekte oder Werte gleich sind
Wenn wir überprüfen wollen, ob der erwartete Wert (oder Objekt) gleich dem tatsächlichen Wert (oder Objekt) ist, müssen wir unsere Behauptung schreiben, indem wir entweder den isEqualTo()
aufrufen Methode des AbstractAssert
Klasse oder der isEqualByComparingTo()
Methode des AbstractComparableAssert
Klasse. Der Unterschied dieser Methoden wird im Folgenden erklärt:
- Der
isEqualTo()
Methode ruft denequals()
auf Methode. - Der
isEqualByComparingTo()
Methode ruft die Methode CompareTo() vonComparable
auf Schnittstelle.
Wenn wir zum Beispiel sicherstellen wollen, dass zwei ganze Zahlen gleich sind, müssen wir eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for objects") class ObjectAssertionTest { @Nested @DisplayName("When two objects are equal") class WhenTwoObjectsAreEqual { @Nested @DisplayName("When objects are integers") class WhenObjectsAreIntegers { private final Integer ACTUAL = 9; private final Integer EXPECTED = 9; @Test @DisplayName("Should be equal") void shouldBeEqual() { assertThat(ACTUAL).isEqualByComparingTo(EXPECTED); } } } }
Wenn wir überprüfen wollen, ob der erwartete Wert (oder Objekt) nicht gleich dem tatsächlichen Wert (oder Objekt) ist, müssen wir unsere Behauptung schreiben, indem wir entweder den isNotEqualTo()
aufrufen Methode des AbstractAssert
Klasse oder der isNotEqualByComparingTo()
Methode des AbstractComparableAssert
Klasse. Diese Methoden werden genauso implementiert wie isEqualTo()
und isEqualByComparingTo()
Methoden.
Wenn wir zum Beispiel sicherstellen wollen, dass zwei ganze Zahlen ungleich sind, müssen wir eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for objects") class ObjectAssertionTest { @Nested @DisplayName("When two objects aren't equal") class WhenTwoObjectsAreNotEqual { @Nested @DisplayName("When objects are integers") class WhenObjectsAreIntegers { private final Integer ACTUAL = 9; private final Integer EXPECTED = 4; @Test @DisplayName("Should not be equal") void shouldNotBeEqual() { assertThat(ACTUAL).isNotEqualByComparingTo(EXPECTED); } } } }
Lassen Sie uns weitermachen und herausfinden, wie wir Zusicherungen für Objektreferenzen schreiben können.
Bestätigen von Objektreferenzen
Wenn wir sicherstellen wollen, dass zwei Objekte auf dasselbe Objekt verweisen, müssen wir unsere Assertion schreiben, indem wir den isSameAs()
aufrufen Methode des AbstractAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for objects") class ObjectAssertionTest { @Nested @DisplayName("When two objects refer to the same object") class WhenTwoObjectsReferToSameObject { private final Object ACTUAL = new Object(); private final Object EXPECTED = ACTUAL; @Test @DisplayName("Should refer to the same object") void shouldReferToSameObject() { assertThat(ACTUAL).isSameAs(EXPECTED); } } }
Wenn wir sicherstellen wollen, dass zwei Objekte nicht auf dasselbe Objekt verweisen, müssen wir unsere Assertion schreiben, indem wir den isNotSameAs()
aufrufen Methode des AbstractAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for objects") class ObjectAssertionTest { @Nested @DisplayName("When two objects don't refer to the same object") class WhenTwoObjectsDoNotReferToSameObject { private final Object ACTUAL = new Object(); private final Object EXPECTED = new Object(); @Test @DisplayName("Should not refer to the same object") void shouldNotReferToSameObject() { assertThat(ACTUAL).isNotSameAs(EXPECTED); } } }
Als nächstes werden wir herausfinden, wie wir überprüfen können, ob zwei Arrays gleich oder ungleich sind.
Behauptung, dass zwei Arrays gleich sind
Wenn wir überprüfen möchten, ob zwei Arrays gleich sind, müssen wir unsere Assertion schreiben, indem wir den isEqualTo()
aufrufen Methode des AbstractArrayAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Write assertions for arrays") class ArrayAssertionTest { @Nested @DisplayName("When two arrays are equal") class WhenArraysAreEqual { @Nested @DisplayName("When arrays contain integers") class WhenArraysContainIntegers { final int[] ACTUAL = new int[]{2, 5, 7}; final int[] EXPECTED = new int[]{2, 5, 7}; @Test @DisplayName("Should contain the same integers") void shouldContainSameIntegers() { assertThat(ACTUAL).isEqualTo(EXPECTED); } } } }
Wenn wir überprüfen möchten, dass zwei Arrays nicht gleich sind, müssen wir unsere Behauptung schreiben, indem wir isNotEqualTo()
aufrufen Methode des AbstractArrayAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Write assertions for arrays") class ArrayAssertionTest { @Nested @DisplayName("When two arrays are not equal") class WhenArraysAreNotEqual { @Nested @DisplayName("When arrays contain integers") class WhenArraysContainIntegers { final int[] ACTUAL = new int[]{2, 6, 7}; final int[] EXPECTED = new int[]{2, 5, 7}; @Test @DisplayName("Should not contain the same integers") void shouldNotContainSameIntegers() { assertThat(ACTUAL).isNotEqualTo(EXPECTED); } } } }
Lassen Sie uns weitermachen und herausfinden, wie wir Zusicherungen für Iterables schreiben können.
Zusicherungen für Iterables schreiben
Wenn wir eine Assertion schreiben wollen, die verifiziert, dass die Größe eines Iterable
richtig ist, können wir eine dieser drei Optionen verwenden:
- Wenn wir überprüfen möchten, ob ein Iterable leer ist, können wir unsere Assertion schreiben, indem wir
isEmpty()
aufrufen Methode desAbstractIterableAssert
Klasse. - Wenn wir sicherstellen wollen, dass ein Iterable nicht leer ist, können wir unsere Assertion schreiben, indem wir
isNotEmpty()
aufrufen Methode desAbstractIterableAssert
Klasse. - Wenn wir überprüfen möchten, ob die Größe des Iterables korrekt ist, können wir unsere Assertion schreiben, indem wir
hasSize()
aufrufen Methode desAbstractIterableAssert
Klasse.
Wenn wir zum Beispiel sicherstellen wollen, dass eine Liste zwei Elemente enthält, müssen wir eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for lists") class ListAssertionTest { @Nested @DisplayName("When we write assertions for elements") class WhenWeWriteAssertionsForElements { private Object first; private Object second; private List<Object> list; @BeforeEach void createAndInitializeList() { first = new Object(); second = new Object(); list = Arrays.asList(first, second); } @Test @DisplayName("Should contain two elements") void shouldContainTwoElements() { assertThat(list).hasSize(2); } } }
Wenn wir sicherstellen wollen, dass ein Iterable nur die erwarteten Elemente in der angegebenen Reihenfolge enthält, müssen wir unsere Assertion mit dem containsExactly()
schreiben Methode des AbstractIterableAssert
Klasse. Wenn wir beispielsweise überprüfen möchten, ob unsere Liste die richtigen Elemente in der angegebenen Reihenfolge enthält, müssen wir diese Behauptung verwenden:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for lists") class ListAssertionTest { @Nested @DisplayName("When we write assertions for elements") class WhenWeWriteAssertionsForElements { private Object first; private Object second; private List<Object> list; @BeforeEach void createAndInitializeList() { first = new Object(); second = new Object(); list = Arrays.asList(first, second); } @Test @DisplayName("Should contain the correct elements in the given order") void shouldContainCorrectElementsInGivenOrder() { assertThat(list).containsExactly(first, second); } } }
Wenn wir überprüfen wollen, ob ein Iterable nur die erwarteten Elemente in beliebiger Reihenfolge enthält, müssen wir unsere Assertion schreiben, indem wir den containsExactlyInAnyOrder()
verwenden Methode des AbstractIterableAssert
Klasse. Wenn wir beispielsweise überprüfen möchten, ob unsere Liste die richtigen Elemente in beliebiger Reihenfolge enthält, müssen wir diese Behauptung verwenden:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for lists") class ListAssertionTest { @Nested @DisplayName("When we write assertions for elements") class WhenWeWriteAssertionsForElements { private Object first; private Object second; private List<Object> list; @BeforeEach void createAndInitializeList() { first = new Object(); second = new Object(); list = Arrays.asList(first, second); } @Test @DisplayName("Should contain the correct elements in any order") void shouldContainCorrectElementsInAnyOrder() { assertThat(list).containsExactlyInAnyOrder(second, first); } } }
Wenn wir sicherstellen wollen, dass ein Iterable das angegebene Element enthält, müssen wir unsere Assertion schreiben, indem wir den containsOnlyOnce()
verwenden Methode des AbstractIterableAssert
Klasse. Zum Beispiel, wenn wir überprüfen möchten, ob unsere Liste den Object
enthält das ist im Feld namens first
gespeichert , müssen wir diese Behauptung verwenden:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for lists") class ListAssertionTest { @Nested @DisplayName("When we write assertions for elements") class WhenWeWriteAssertionsForElements { private Object first; private Object second; private List<Object> list; @BeforeEach void createAndInitializeList() { first = new Object(); second = new Object(); list = Arrays.asList(first, second); } @Test @DisplayName("Should contain the correct element once") void shouldContainCorrectElementOnce() { assertThat(list).containsOnlyOnce(first); } } }
Wenn wir sicherstellen wollen, dass ein Iterable das angegebene Element nicht enthält, müssen wir unsere Assertion schreiben, indem wir den doesNotContain()
verwenden Methode des AbstractIterableAssert
Klasse. Wenn wir beispielsweise überprüfen möchten, ob unsere Liste das angegebene Objekt nicht enthält, müssen wir diese Behauptung verwenden:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for lists") class ListAssertionTest { @Nested @DisplayName("When we write assertions for elements") class WhenWeWriteAssertionsForElements { private Object first; private Object second; private List<Object> list; @BeforeEach void createAndInitializeList() { first = new Object(); second = new Object(); list = Arrays.asList(first, second); } @Test @DisplayName("Should not contain an incorrect element") void shouldNotContainIncorrectElement() { assertThat(list).doesNotContain(new Object()); } } }
Wenn wir überprüfen wollen, ob zwei Iterables absolut gleich sind, müssen wir unsere Assertion schreiben, indem wir den isEqualTo()
verwenden Methode des AbstractAssert
Klasse. Zum Beispiel, wenn wir überprüfen wollen, ob zwei Integer
Listen zutiefst gleich sind, müssen wir diese Behauptung verwenden:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for lists") class ListAssertionTest { @Nested @DisplayName("When we compare two lists") class WhenWeCompareTwoLists { private final List<Integer> FIRST = Arrays.asList(1, 2, 3); private final List<Integer> SECOND = Arrays.asList(1, 2, 3); @Test @DisplayName("Should contain the same elements") void shouldContainSameElements() { assertThat(FIRST).isEqualTo(SECOND); } } }
Als nächstes werden wir herausfinden, wie wir Zusicherungen für Karten schreiben können.
Aussagen für Karten schreiben
Wenn wir sicherstellen wollen, dass eine Map den angegebenen Schlüssel enthält, müssen wir unsere Assertion schreiben, indem wir den containsKey()
aufrufen Methode des AbstractMapAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for maps") class MapAssertionTest { private static final String INCORRECT_KEY = "incorrectKey"; private static final String KEY = "key"; private static final String VALUE = "value"; private Map<String, String> map; @BeforeEach void createAndInitializeMap() { map = new HashMap<>(); map.put(KEY, VALUE); } @Nested @DisplayName("When we verify that the map contains the given key") class WhenWeVerifyThatMapContainsGivenKey { @Test @DisplayName("Should contain the correct key") void shouldContainCorrectKey() { assertThat(map).containsKey(KEY); } } }
Wenn wir sicherstellen wollen, dass eine Map den angegebenen Schlüssel nicht enthält, müssen wir unsere Assertion schreiben, indem wir den doesNotContainKey()
aufrufen Methode des AbstractMapAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for maps") class MapAssertionTest { private static final String INCORRECT_KEY = "incorrectKey"; private static final String KEY = "key"; private static final String VALUE = "value"; private Map<String, String> map; @BeforeEach void createAndInitializeMap() { map = new HashMap<>(); map.put(KEY, VALUE); } @Nested @DisplayName("When we verify that the map doesn't contain the given key") class WhenWeVerifyThatMapDoesNotContainGivenKey { @Test @DisplayName("Should not contain the incorrect key") void shouldNotContainIncorrectKey() { assertThat(map).doesNotContainKey(INCORRECT_KEY); } } }
Wenn wir sicherstellen wollen, dass eine Map den angegebenen Eintrag enthält, müssen wir unsere Assertion schreiben, indem wir den containsEntry()
aufrufen Methode des AbstractMapAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for maps") class MapAssertionTest { private static final String INCORRECT_KEY = "incorrectKey"; private static final String KEY = "key"; private static final String VALUE = "value"; private Map<String, String> map; @BeforeEach void createAndInitializeMap() { map = new HashMap<>(); map.put(KEY, VALUE); } @Nested @DisplayName("When we verify that the map contains the given entry") class WhenWeVerifyThatMapContainsGivenEntry { @Test @DisplayName("Should contain the given entry") void shouldContainGivenEntry() { assertThat(map).containsEntry(KEY, VALUE); } } }
Wenn wir sicherstellen wollen, dass eine Map den angegebenen Eintrag nicht enthält, müssen wir unsere Assertion schreiben, indem wir den doesNotContainEntry()
aufrufen Methode des AbstractMapAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion verwenden, die wie folgt aussieht:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for maps") class MapAssertionTest { private static final String INCORRECT_KEY = "incorrectKey"; private static final String KEY = "key"; private static final String VALUE = "value"; private Map<String, String> map; @BeforeEach void createAndInitializeMap() { map = new HashMap<>(); map.put(KEY, VALUE); } @Nested @DisplayName("When we verify that the map doesn't contain the given entry") class WhenWeVerifyThatMapDoesNotContainGivenEntry { @Test @DisplayName("Should not contain the given entry") void shouldContainGivenEntry() { assertThat(map).doesNotContainEntry(INCORRECT_KEY, VALUE); } } }
Lassen Sie uns weitermachen und herausfinden, wie wir Zusicherungen für die vom zu testenden System ausgelösten Ausnahmen schreiben können.
Zusicherungen für Ausnahmen schreiben
Wenn wir Zusicherungen für die vom zu testenden System ausgelöste Ausnahme schreiben möchten, können wir eine dieser beiden Optionen verwenden:
Zuerst , können wir den static assertThatThrownBy()
verwenden Methode des org.assertj.core.api.Assertions
Klasse. Wenn wir diese Methode verwenden, müssen wir diese zwei Dinge wissen:
- Es dauert ein
ThrowingCallable
Objekt als Methodenparameter. Dieses Objekt ruft das zu testende System auf. - Es wird ein
AbstractThrowableAssert
zurückgegeben Objekt. Wir müssen dieses Objekt verwenden, wenn wir Zusicherungen für die vom zu testenden System ausgelöste Ausnahme schreiben.
Schauen wir uns zwei Beispiele an, die zeigen, wie wir mit diesem Ansatz Behauptungen schreiben können:
Wenn wir überprüfen möchten, ob das zu testende System die erwartete Ausnahme auslöst, müssen wir unsere Assertion mit dem isExactlyInstanceOf()
schreiben Methode des AbstractThrowableAssert
Klasse. Wenn wir beispielsweise überprüfen möchten, ob das zu testende System einen NullPointerException
auslöst , müssen wir eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; @DisplayName("Writing assertions for exceptions") class ExceptionAssertionTest { @Nested @DisplayName("When we write assertions directly to the thrown exception") class WhenWeWriteAssertionsForThrownException { @Nested @DisplayName("When the system under test throws the correct exception") class WhenSystemUnderTestThrowsException { @Test @DisplayName("Should throw the correct exception") void shouldThrowCorrectException() { assertThatThrownBy(() -> { throw new NullPointerException(); }) .isExactlyInstanceOf(NullPointerException.class); } } } }
Wenn wir überprüfen möchten, ob das zu testende System eine Ausnahme mit der erwarteten Nachricht auslöst, müssen wir unsere Assertion mit hasMessage()
schreiben Methode des AbstractThrowableAssert
Klasse. Wenn wir beispielsweise überprüfen möchten, ob das zu testende System eine Ausnahme mit der Nachricht „Hello World!“ auslöst, müssen wir eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; @DisplayName("Writing assertions for exceptions") class ExceptionAssertionTest { @Nested @DisplayName("When we write assertions directly to the thrown exception") class WhenWeWriteAssertionsForThrownException { @Nested @DisplayName("When SUT throws an exception that has the correct message") class WhenSystemUnderTestThrowsExceptionWithCorrectMessage { @Test @DisplayName("Should throw an exception that has the correct message") void shouldThrowAnExceptionWithCorrectMessage() { assertThatThrownBy(() -> { throw new NullPointerException("Hello World!"); }) .hasMessage("Hello World!"); } } } }
Zweite , können wir die ausgelöste Ausnahme mithilfe von static catchThrowable()
abfangen Methode des org.assertj.core.api.Assertions
Klasse. Diese Methode kann zwei Methodenparameter annehmen, die im Folgenden beschrieben werden:
- Ein
ThrowingCallable
Objekt, das das zu testende System aufruft. - A
Class
Objekt, das den Typ der erwarteten Ausnahme angibt. Dies ist ein optionaler Parameter, und wenn wir ihn ancatchThrowable()
übergeben -Methode gibt sie den Typ des zurückgegebenen Ausnahmeobjekts an. Wenn wir diesen Methodenparameter weglassen, wird dercatchThrowable()
Methode gibt einenThrowable
zurück Objekt.
Schauen wir uns zwei Beispiele an, die zeigen, wie wir mit diesem Ansatz Behauptungen schreiben können:
Wenn wir überprüfen möchten, ob das zu testende System die erwartete Ausnahme auslöst, müssen wir unsere Assertion mit dem isExactlyInstanceOf()
schreiben Methode des AbstractThrowableAssert
Klasse. Wenn wir beispielsweise überprüfen möchten, ob das zu testende System einen NullPointerException
auslöst , müssen wir eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @DisplayName("Writing assertions for exceptions") class ExceptionAssertionTest { @Nested @DisplayName("When we catch the thrown exception object") class WhenWeCatchThrownExceptionObject { @Nested @DisplayName("When the system under test throws the correct exception") class WhenSystemUnderTestThrowsException { @Test @DisplayName("Should throw the correct exception") void shouldThrowCorrectException() { final Throwable thrown = catchThrowable(() -> { throw new NullPointerException(); }); assertThat(thrown).isExactlyInstanceOf(NullPointerException.class); } } } }
Wenn wir überprüfen möchten, ob das zu testende System eine Ausnahme mit der erwarteten Nachricht auslöst, müssen wir unsere Assertion mit dem hasMessage()
schreiben Methode des AbstractThrowableAssert
Klasse. Wenn wir beispielsweise überprüfen möchten, ob das zu testende System eine Ausnahme mit der Nachricht „Hello World!“ auslöst, müssen wir eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @DisplayName("Writing assertions for exceptions") class ExceptionAssertionTest { @Nested @DisplayName("When we catch the thrown exception object") class WhenWeCatchThrownExceptionObject { @Nested @DisplayName("When the system under test throws an exception that has the correct message") class WhenSystemUnderTestThrowsExceptionWithCorrectMessage { @Test @DisplayName("Should throw an exception that has the correct message") void shouldThrowAnExceptionWithCorrectMessage() { final Throwable thrown = catchThrowable(() -> { throw new NullPointerException("Hello World!"); } ); assertThat(thrown.getMessage()).isEqualTo("Hello World!"); } } } }
Als nächstes werden wir herausfinden, wie wir Zusicherungen für Optional
schreiben können Objekte.
Zusicherungen für optionale Objekte schreiben
Wenn wir sicherstellen wollen, dass ein Optional
Objekt leer ist, müssen wir unsere Assertion schreiben, indem wir isEmpty()
aufrufen Methode des AbstractOptionalAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for Optional objects") class OptionalAssertionTest { @Nested @DisplayName("When the optional is empty") class WhenOptionalIsEmpty { @Test @DisplayName("Should be empty") void shouldBeEmpty() { assertThat(Optional.empty()).isEmpty(); } } }
Wenn wir sicherstellen wollen, dass ein Optional
Objekt nicht leer ist, müssen wir unsere Assertion schreiben, indem wir isNotEmpty()
aufrufen Methode des AbstractOptionalAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for Optional objects") class OptionalAssertionTest { @Nested @DisplayName("When the optional is not empty") class WhenOptionalIsNotEmpty { @Test @DisplayName("Should not be empty") void shouldNotBeEmpty() { assertThat(Optional.of(new Object())).isNotEmpty(); } } }
Wenn wir sicherstellen wollen, dass ein Optional
Objekt das erwartete Objekt enthält, müssen wir unsere Assertion schreiben, indem wir contains()
aufrufen Methode des AbstractOptionalAssert
Klasse. Mit anderen Worten, wir müssen eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Writing assertions for Optional objects") class OptionalAssertionTest { @Nested @DisplayName("When the optional is not empty") class WhenOptionalIsNotEmpty { private final Object OBJECT = new Object(); @Test @DisplayName("Should contain the correct object") void shouldContainCorrectObject() { assertThat(Optional.of(OBJECT)).contains(OBJECT); } } }
Lassen Sie uns weitermachen und herausfinden, wie wir eine benutzerdefinierte Fehlermeldung angeben können, die angezeigt wird, wenn eine Assertion fehlschlägt.
Eine benutzerdefinierte Fehlermeldung bereitstellen
Obwohl AssertJ sehr gute Fehlermeldungen hat, möchten wir manchmal die Geschäftsregel hervorheben, die durch unsere Assertion erzwungen wird. Wenn wir dies tun möchten, können wir eine benutzerdefinierte Fehlermeldung bereitstellen, indem wir eine dieser beiden Optionen verwenden:
- Wenn wir den Beschreibungsteil der Fehlermeldung überschreiben wollen, müssen wir entweder den
as()
aufrufen oder diedescribedAs()
Methode desDescriptable
Schnittstelle. - Wenn wir die gesamte Fehlermeldung überschreiben wollen, müssen wir den
overridingErrorMessage()
aufrufen Methode desAbstractAssert
Klasse.
Alle diese Methoden können zwei Methodenparameter annehmen, die im Folgenden erklärt werden:
- A
String
Objekt, das die Fehlermeldung enthält. Wenn wir eine dynamische Fehlermeldung bereitstellen möchten, können wir das vonString.format()
unterstützte Format verwenden Methode. - Ein optionaler
Object
Array, das die Parameter unserer Fehlermeldung enthält. Dieser Methodenparameter wird anString.format()
übergeben Methode, die die eigentliche Fehlermeldung erstellt. Deshalb müssen wir diesen Methodenparameter nicht angeben, wenn wir eine statische Fehlermeldung verwenden.
Schauen wir uns zwei Beispiele an, die den Unterschied dieser Optionen demonstrieren.
Zuerst , wenn wir nur den Beschreibungsteil der angezeigten Fehlermeldung überschreiben wollen, müssen wir eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Provide a custom error message") class CustomErrorMessageTest { @Nested @DisplayName("When we provide only the description") class WhenWeProvideOnlyDescription { @Test @DisplayName("Should override only the description") void shouldBeFalseWithCustomErrorMessage() { assertThat(false) .describedAs("The boolean is not false") .isFalse(); } } }
Wenn unsere Assertion fehlschlägt, sehen wir eine Fehlermeldung, die wie folgt aussieht:
org.opentest4j.AssertionFailedError: [The boolean is not false] Expecting: <true> to be equal to: <false> but was not. Expected :false Actual :true
Zweite , wenn wir die gesamte Fehlermeldung überschreiben wollen, müssen wir eine Assertion schreiben, die wie folgt aussieht:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @DisplayName("Provide a custom error message") class CustomErrorMessageTest { @Nested @DisplayName("When we provide the entire error message") class WhenWeProvideEntireErrorMessage { @Test @DisplayName("Should override entire error message") void shouldBeFalseWithCustomErrorMessage() { assertThat(false) .overridingErrorMessage("The boolean is not false") .isFalse(); } } }
Wenn unsere Assertion fehlschlägt, sehen wir eine Fehlermeldung, die wie folgt aussieht:
java.lang.AssertionError: The boolean is not false
Lassen Sie uns weitermachen und herausfinden, wie wir mit AssertJ weiche Behauptungen schreiben können.
Weiche Behauptungen schreiben
Wenn wir eine Zusicherung für einen Zustand schreiben müssen, der mehrere Zusicherungen erfordert, ist es eine gute Idee, alle Zusicherungen auszuführen und alle Zusicherungsfehler zu melden, nachdem alle Zusicherungen ausgeführt wurden. Wir können dies mit AssertJ tun, indem wir weiche Zusicherungen verwenden.
Nehmen wir an, wir müssen eine Assertion schreiben, die verifiziert, dass ein Person
Objekt hat den richtigen Namen. Der Quellcode von Person
Klasse sieht wie folgt aus:
public class Person { private String firstName; private String lastName; public Person() {} public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setLastName(String lastName) { this.lastName = lastName; } }
Wie wir sehen können, müssen wir, wenn wir überprüfen wollen, ob eine Person den richtigen Namen hat, überprüfen, ob der geltend gemachte Person
Objekt hat den richtigen Vor- und Nachnamen. Wir können unsere Assertion schreiben, indem wir diesen Schritten folgen:
- Erstellen Sie einen neuen
SoftAssertions
Objekt. - Stellen Sie sicher, dass
Person
Objekt hat den richtigen Vornamen. - Vergewissern Sie sich, dass
Person
Objekt hat den richtigen Nachnamen. - Führen Sie alle Behauptungen durch Aufrufen von
assertAll()
aus Methode desSoftAssertions
Klasse. Diese Methode führt alle angegebenen Zusicherungen aus und meldet Zusicherungsfehler, nachdem diese Zusicherungen ausgeführt wurden.
Nachdem wir die erforderlichen Soft Assertions geschrieben haben, sieht der Quellcode unserer Testklasse wie folgt aus:
import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("Collect all error messages before reporting them") class SoftAssertionsTest { private static final String FIRST_NAME = "Jane"; private static final String LAST_NAME = "Doe"; private Person person; @BeforeEach void createPerson() { person = new Person(); person.setFirstName(FIRST_NAME); person.setLastName(LAST_NAME); } @Test @DisplayName("Should have the correct name") void shouldHaveCorrectName() { SoftAssertions softAssertions = new SoftAssertions(); softAssertions.assertThat(person.getFirstName()) .overridingErrorMessage( "Expected the first name to be: %s but it was: %s", FIRST_NAME, person.getFirstName() ) .isEqualTo(FIRST_NAME); softAssertions.assertThat(person.getLastName()) .overridingErrorMessage( "Expected the last name to be: %s but it was: %s", LAST_NAME, person.getLastName() ) .isEqualTo(LAST_NAME); softAssertions.assertAll(); } }
Wir können jetzt grundlegende Zusicherungen mit AssertJ schreiben, eine benutzerdefinierte Fehlermeldung bereitstellen, die angezeigt wird, wenn eine Zusicherung fehlschlägt, und weiche Zusicherungen mit AssertJ schreiben.
Fassen wir zusammen, was wir aus diesem Blogbeitrag gelernt haben.
Zusammenfassung
Dieser Blogbeitrag hat uns fünf Dinge beigebracht:
- Bevor wir Assertions mit AssertJ schreiben können, müssen wir sicherstellen, dass der
assertj-core
Abhängigkeit wird aus dem Klassenpfad gefunden. - Wir können Behauptungen mit AssertJ schreiben, indem wir den
static
verwenden Methoden derorg.assertj.core.api.Assertions
Klasse. - Wenn wir den Beschreibungsteil der Fehlermeldung überschreiben wollen, der angezeigt wird, wenn eine Behauptung fehlschlägt, müssen wir entweder den
as()
verwenden oderdescribedAs()
Methoden desDescriptable
Schnittstelle. - Wenn wir die gesamte Fehlermeldung überschreiben wollen, die angezeigt wird, wenn eine Assertion fehlschlägt, müssen wir den
overridingErrorMessage()
aufrufen Methode desAbstractAssert
Klasse. - Wir können mit AssertJ Soft-Assertionen schreiben, indem wir den
org.assertj.core.api.SoftAssertions
verwenden Klasse.