Java >> Java Tutorial >  >> Tag >> assert

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 von assertThat() 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 den equals() auf Methode.
  • Der isEqualByComparingTo() Methode ruft die Methode CompareTo() von Comparable 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 des AbstractIterableAssert Klasse.
  • Wenn wir sicherstellen wollen, dass ein Iterable nicht leer ist, können wir unsere Assertion schreiben, indem wir isNotEmpty() aufrufen Methode des AbstractIterableAssert 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 des AbstractIterableAssert 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 an catchThrowable() übergeben -Methode gibt sie den Typ des zurückgegebenen Ausnahmeobjekts an. Wenn wir diesen Methodenparameter weglassen, wird der catchThrowable() Methode gibt einen Throwable 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 die describedAs() Methode des Descriptable Schnittstelle.
  • Wenn wir die gesamte Fehlermeldung überschreiben wollen, müssen wir den overridingErrorMessage() aufrufen Methode des AbstractAssert 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 von String.format() unterstützte Format verwenden Methode.
  • Ein optionaler Object Array, das die Parameter unserer Fehlermeldung enthält. Dieser Methodenparameter wird an String.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:

  1. Erstellen Sie einen neuen SoftAssertions Objekt.
  2. Stellen Sie sicher, dass Person Objekt hat den richtigen Vornamen.
  3. Vergewissern Sie sich, dass Person Objekt hat den richtigen Nachnamen.
  4. Führen Sie alle Behauptungen durch Aufrufen von assertAll() aus Methode des SoftAssertions 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 der org.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 oder describedAs() Methoden des Descriptable Schnittstelle.
  • Wenn wir die gesamte Fehlermeldung überschreiben wollen, die angezeigt wird, wenn eine Assertion fehlschlägt, müssen wir den overridingErrorMessage() aufrufen Methode des AbstractAssert Klasse.
  • Wir können mit AssertJ Soft-Assertionen schreiben, indem wir den org.assertj.core.api.SoftAssertions verwenden Klasse.

Java-Tag