JUnit 5 Tutorial:At skrive påstande med AssertJ
Dette blogindlæg beskriver, hvordan vi kan skrive påstande med AssertJ. Efter at vi har afsluttet dette blogindlæg, gør vi:
- Kan få de nødvendige afhængigheder med Maven og Gradle.
- Vid, hvordan vi kan skrive grundlæggende påstande med AssertJ.
- Forstå, hvordan vi kan tilpasse den fejlmeddelelse, der vises, når en påstand mislykkes.
- Kan skrive bløde påstande med AssertJ.
Lad os begynde.
Få de nødvendige afhængigheder
Før vi kan skrive påstande med AssertJ, skal vi sikre, at assertj-core
afhængighed (version 3.21.0) findes fra klassestien.
Hvis vi bruger Maven, skal vi tilføje assertj-core
afhængighed af test
omfang. Vi kan gøre dette ved at tilføje følgende uddrag til dependencies
sektion af vores pom.xml fil:
<dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.21.0</version> <scope>test</scope> </dependency>
Hvis vi bruger Gradle, skal vi tilføje assertj-core
afhængighed af testImplementation
afhængighedskonfiguration. Vi kan gøre dette ved at tilføje følgende uddrag til vores build.gradle fil:
dependencies { testImplementation( 'org.assertj:assertj-core:3.21.0' ) }
Efter at vi har tilføjet denne afhængighed til klassestien, kan vi skrive påstande med AssertJ. Lad os finde ud af, hvordan vi kan gøre det.
Skriv påstande med AssertJ
Når vi vil skrive påstande med AssertJ, skal vi bruge static assertThat()
metoden for org.assertj.core.api.Assertions
klasse. Når vi påberåber os denne metode, skal vi vide disse to ting:
assertThat()
metoden tager den faktiske værdi eller objektet som en metodeparameter.Assertions()
klasse bruger metodeoverbelastning og typen af objektet, der returneres afassertThat()
metode afhænger af typen af argumentet, der overføres til den pågældende metode.
Efter at vi har påkaldt assertThat()
metode, kan vi skrive vores påstande ved at bruge det returnerede assertion objekt. Da AssertJ også leverer en flydende API, returnerer hver påstandsmetode en reference til det brugte påstandsobjekt. Det betyder, at vi kan sammenkæde påstande ved blot at påberåbe os en anden påstandsmetode.
Dernæst vil vi tage et kig på nogle eksempler, som viser, hvordan vi kan skrive påstande med AssertJ.
Bekræftelse af booleske værdier
Hvis vi ønsker at verificere, at en boolean
værdien er true
, skal vi skrive vores påstand ved at kalde isTrue()
metode for AbstractBooleanAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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(); } } }
Hvis vi ønsker at bekræfte, at en boolean
værdien er false
, skal vi skrive vores påstand ved at påkalde isFalse()
metoden for AbstractBooleanAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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(); } } }
Lad os gå videre og finde ud af, hvordan vi kan verificere, at et objekt er null
eller er det ikke null
.
Bekræftelse af, at et objekt er nul eller ikke er nul
Hvis vi vil verificere at et objekt er null
, skal vi skrive vores påstand ved at kalde isNull()
metoden for AbstractAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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(); } } }
Hvis vi vil verificere, at et objekt ikke er null
, skal vi skrive vores påstand ved at kalde isNotNull()
metode for AbstractAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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(); } } }
Dernæst vil vi finde ud af, hvordan vi kan verificere, at to objekter (eller værdier) er ens eller ikke er ens.
Bekræftelse af, at to objekter eller værdier er ens
Hvis vi ønsker at verificere, at den forventede værdi (eller objekt) er lig med den faktiske værdi (eller objekt), skal vi skrive vores påstand ved at påkalde enten isEqualTo()
metode for AbstractAssert
klasse eller isEqualByComparingTo()
metoden for AbstractComparableAssert
klasse. Forskellen på disse metoder er forklaret i det følgende:
isEqualTo()
metode kalderequals()
metode.isEqualByComparingTo()
metoden kalder compareTo() metoden tilComparable
grænseflade.
For eksempel, hvis vi vil sikre, at to heltal er lige store, skal vi bruge en påstand, der ser ud som følger:
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); } } } }
Hvis vi vil verificere, at den forventede værdi (eller objekt) ikke er lig med den faktiske værdi (eller objekt), skal vi skrive vores påstand ved at påkalde enten isNotEqualTo()
metoden for AbstractAssert
klasse eller isNotEqualByComparingTo()
metoden for AbstractComparableAssert
klasse. Disse metoder implementeres på samme måde som isEqualTo()
og isEqualByComparingTo()
metoder.
For eksempel, hvis vi vil sikre, at to heltal ikke er ens, skal vi bruge en påstand, der ser ud som følger:
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); } } } }
Lad os gå videre og finde ud af, hvordan vi kan skrive påstande til objektreferencer.
Påhævelse af objektreferencer
Hvis vi vil sikre, at to objekter refererer til det samme objekt, skal vi skrive vores påstand ved at kalde isSameAs()
metoden for AbstractAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } }
Hvis vi vil sikre, at to objekter ikke refererer til det samme objekt, skal vi skrive vores påstand ved at påkalde isNotSameAs()
metoden for AbstractAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } }
Dernæst vil vi finde ud af, hvordan vi kan verificere, at to arrays er ens eller ikke er ens.
påstand om, at to arrays er ens
Hvis vi vil verificere, at to arrays er ens, skal vi skrive vores påstand ved at kalde isEqualTo()
metoden for AbstractArrayAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } } }
Hvis vi vil verificere, at to arrays ikke er ens, skal vi skrive vores påstand ved at kalde isNotEqualTo()
metoden for AbstractArrayAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } } }
Lad os gå videre og finde ud af, hvordan vi kan skrive påstande til iterables.
Skrivning af påstande for iterables
Hvis vi ønsker at skrive en påstand, som bekræfter, at størrelsen af en Iterable
er korrekt, kan vi bruge en af disse tre muligheder:
- Hvis vi vil bekræfte, at en iterabel er tom, kan vi skrive vores påstand ved at påkalde
isEmpty()
metoden forAbstractIterableAssert
klasse. - Hvis vi vil sikre, at en iterabel ikke er tom, kan vi skrive vores påstand ved at påkalde
isNotEmpty()
metoden forAbstractIterableAssert
klasse. - Hvis vi ønsker at verificere, at størrelsen af den iterable er korrekt, kan vi skrive vores påstand ved at påkalde
hasSize()
metoden forAbstractIterableAssert
klasse.
For eksempel, hvis vi vil sikre, at en liste indeholder to elementer, skal vi bruge en påstand, der ser ud som følger:
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); } } }
Hvis vi vil sikre, at en iterabel kun indeholder de forventede elementer i den givne rækkefølge, skal vi skrive vores påstand ved at bruge containsExactly()
metoden for AbstractIterableAssert
klasse. For eksempel, hvis vi vil verificere, at vores liste indeholder de korrekte elementer i den givne rækkefølge, skal vi bruge denne påstand:
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); } } }
Hvis vi vil verificere, at en iterabel kun indeholder de forventede elementer i en hvilken som helst rækkefølge, skal vi skrive vores påstand ved at bruge containsExactlyInAnyOrder()
metoden for AbstractIterableAssert
klasse. For eksempel, hvis vi vil verificere, at vores liste indeholder de korrekte elementer i en hvilken som helst rækkefølge, skal vi bruge denne påstand:
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); } } }
Hvis vi vil sikre, at en iterabel indeholder det angivne element, skal vi skrive vores påstand ved at bruge containsOnlyOnce()
metode for AbstractIterableAssert
klasse. For eksempel, hvis vi ønsker at bekræfte, at vores liste indeholder Object
der er gemt i feltet kaldet first
, vi skal bruge denne påstand:
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); } } }
Hvis vi vil sikre, at en iterable ikke indeholder det angivne element, skal vi skrive vores påstand ved at bruge doesNotContain()
metoden for AbstractIterableAssert
klasse. For eksempel, hvis vi vil verificere, at vores liste ikke indeholder det angivne objekt, skal vi bruge denne påstand:
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()); } } }
Hvis vi vil verificere, at to iterables er dybt lige store, skal vi skrive vores påstand ved at bruge isEqualTo()
metoden for AbstractAssert
klasse. For eksempel, hvis vi vil bekræfte, at to Integer
lister er dybt lige, skal vi bruge denne påstand:
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); } } }
Dernæst vil vi finde ud af, hvordan vi kan skrive påstande til kort.
Skriv påstande til kort
Hvis vi vil sikre, at et kort indeholder den angivne nøgle, skal vi skrive vores påstand ved at påkalde containsKey()
metoden for AbstractMapAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } }
Hvis vi vil sikre, at et kort ikke indeholder den angivne nøgle, skal vi skrive vores påstand ved at påkalde doesNotContainKey()
metoden for AbstractMapAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } }
Hvis vi vil sikre, at et kort indeholder den angivne post, skal vi skrive vores påstand ved at påkalde containsEntry()
metoden for AbstractMapAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } }
Hvis vi vil sikre, at et kort ikke indeholder den angivne post, skal vi skrive vores påstand ved at påkalde doesNotContainEntry()
metoden for AbstractMapAssert
klasse. Med andre ord skal vi bruge en påstand, der ser ud som følger:
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); } } }
Lad os gå videre og finde ud af, hvordan vi kan skrive påstande for de undtagelser, som det system, der testes, giver.
Skrive påstande for undtagelser
Hvis vi ønsker at skrive påstande for den undtagelse, der er smidt af systemet under test, kan vi bruge en af disse to muligheder:
Først , kan vi bruge static assertThatThrownBy()
metode for org.assertj.core.api.Assertions
klasse. Når vi bruger denne metode, skal vi vide disse to ting:
- Det kræver en
ThrowingCallable
objekt som metodeparameter. Dette objekt kalder systemet under test. - Det returnerer en
AbstractThrowableAssert
objekt. Vi er nødt til at bruge dette objekt, når vi skriver påstande for den undtagelse, der er smidt af systemet under test.
Lad os tage et kig på to eksempler, der viser, hvordan vi kan skrive påstande ved at bruge denne tilgang:
Hvis vi vil verificere, at systemet under test afgiver den forventede undtagelse, skal vi skrive vores påstand ved at bruge isExactlyInstanceOf()
metoden for AbstractThrowableAssert
klasse. For eksempel, hvis vi ønsker at verificere, at systemet under test kaster en NullPointerException
, skal vi skrive en påstand, der ser ud som følger:
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); } } } }
Hvis vi ønsker at verificere, at systemet under test afgiver en undtagelse, der har den forventede besked, skal vi skrive vores påstand ved at bruge hasMessage()
metoden for AbstractThrowableAssert
klasse. For eksempel, hvis vi ønsker at verificere, at systemet under test afgiver en undtagelse, der har meddelelsen:'Hello World!', skal vi skrive en påstand, der ser ud som følger:
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!"); } } } }
Anden , kan vi fange den kastede undtagelse ved at bruge static catchThrowable()
metoden for org.assertj.core.api.Assertions
klasse. Denne metode kan tage to metodeparametre, som er beskrevet i det følgende:
- A
ThrowingCallable
objekt, der kalder systemet under test. - A
Class
objekt, der angiver typen af den forventede undtagelse. Dette er en valgfri parameter, og hvis vi sender den tilcatchThrowable()
metode, angiver den typen af det returnerede undtagelsesobjekt. Hvis vi udelader denne metodeparameter, vilcatchThrowable()
metode returnerer enThrowable
objekt.
Lad os tage et kig på to eksempler, der viser, hvordan vi kan skrive påstande ved at bruge denne tilgang:
Hvis vi vil verificere, at systemet under test afgiver den forventede undtagelse, skal vi skrive vores påstand ved at bruge isExactlyInstanceOf()
metoden for AbstractThrowableAssert
klasse. For eksempel, hvis vi ønsker at verificere, at systemet under test kaster en NullPointerException
, skal vi skrive en påstand, der ser ud som følger:
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); } } } }
Hvis vi vil verificere, at systemet under test afgiver en undtagelse, der har den forventede besked, skal vi skrive vores påstand ved at bruge hasMessage()
metoden for AbstractThrowableAssert
klasse. For eksempel, hvis vi ønsker at verificere, at systemet under test afgiver en undtagelse, der har meddelelsen:'Hello World!', skal vi skrive en påstand, der ser ud som følger:
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!"); } } } }
Dernæst vil vi finde ud af, hvordan vi kan skrive påstande for Optional
genstande.
Skrivning af påstande til valgfrie objekter
Hvis vi ønsker at sikre, at en Optional
objektet er tomt, skal vi skrive vores påstand ved at kalde isEmpty()
metoden for AbstractOptionalAssert
klasse. Med andre ord skal vi skrive en påstand, der ser ud som følger:
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(); } } }
Hvis vi ønsker at sikre, at en Optional
objektet ikke er tomt, skal vi skrive vores påstand ved at påkalde isNotEmpty()
metode for AbstractOptionalAssert
klasse. Med andre ord skal vi skrive en påstand, der ser ud som følger:
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(); } } }
Hvis vi ønsker at sikre, at en Optional
objektet indeholder det forventede objekt, skal vi skrive vores påstand ved at kalde contains()
metoden for AbstractOptionalAssert
klasse. Med andre ord skal vi skrive en påstand, der ser ud som følger:
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); } } }
Lad os gå videre og finde ud af, hvordan vi kan angive en brugerdefineret fejlmeddelelse, der vises, når en påstand mislykkes.
Udgivelse af en brugerdefineret fejlmeddelelse
Selvom AssertJ har meget gode fejlmeddelelser, vil vi nogle gange gerne understrege den forretningsregel, der håndhæves af vores påstand. Når vi ønsker at gøre dette, kan vi give en brugerdefineret fejlmeddelelse ved at bruge en af disse to muligheder:
- Hvis vi ønsker at tilsidesætte beskrivelsesdelen af fejlmeddelelsen, skal vi enten kalde
as()
ellerdescribedAs()
metoden forDescriptable
grænseflade. - Hvis vi vil tilsidesætte hele fejlmeddelelsen, skal vi aktivere
overridingErrorMessage()
metoden forAbstractAssert
klasse.
Alle disse metoder kan tage to metodeparametre, som er forklaret i det følgende:
- A
String
objekt, som indeholder fejlmeddelelsen. Hvis vi ønsker at give en dynamisk fejlmeddelelse, kan vi bruge formatet understøttet afString.format()
metode. - En valgfri
Object
array, som indeholder parametrene for vores fejlmeddelelse. Denne metodeparameter sendes tilString.format()
metode, der opretter den faktiske fejlmeddelelse. Det er derfor, vi ikke behøver at give denne metodeparameter, hvis vi bruger en statisk fejlmeddelelse.
Lad os tage et kig på to eksempler, der viser forskellen på disse muligheder.
Først , hvis vi kun ønsker at tilsidesætte beskrivelsesdelen af den viste fejlmeddelelse, skal vi skrive en påstand, der ser ud som følger:
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(); } } }
Hvis vores påstand mislykkes, ser vi en fejlmeddelelse, der ser ud som følger:
org.opentest4j.AssertionFailedError: [The boolean is not false] Expecting: <true> to be equal to: <false> but was not. Expected :false Actual :true
Anden , hvis vi vil tilsidesætte hele fejlmeddelelsen, skal vi skrive en påstand, der ser ud som følger:
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(); } } }
Hvis vores påstand mislykkes, ser vi en fejlmeddelelse, der ser ud som følger:
java.lang.AssertionError: The boolean is not false
Lad os gå videre og finde ud af, hvordan vi kan skrive bløde påstande med AssertJ.
Skriv bløde påstande
Hvis vi skal skrive en påstand for en tilstand, der kræver flere påstande, er det en god idé at køre alle påstande og rapportere alle påstandsfejl, efter at alle påstande er blevet kørt. Vi kan gøre dette med AssertJ ved at bruge bløde påstande.
Lad os antage, at vi skal skrive en påstand, der bekræfter, at en Person
objektet har det korrekte navn. Kildekoden til Person
klasse ser ud som følger:
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; } }
Som vi kan se, hvis vi vil verificere, at en person har det korrekte navn, skal vi verificere, at den påståede Person
objektet har det korrekte for- og efternavn. Vi kan skrive vores påstand ved at følge disse trin:
- Opret en ny
SoftAssertions
objekt. - Sørg for, at
Person
objektet har det korrekte fornavn. - Bekræft, at
Person
objektet har det korrekte efternavn. - Kør alle påstande ved at kalde
assertAll()
metode tilSoftAssertions
klasse. Denne metode kører alle specificerede påstande og rapporterer påstandsfejl, efter at disse påstande er blevet kørt.
Efter at vi har skrevet de påkrævede bløde påstande, ser kildekoden for vores testklasse ud som følger:
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(); } }
Vi kan nu skrive grundlæggende påstande med AssertJ, give en brugerdefineret fejlmeddelelse, der vises, når en påstand mislykkes, og skrive bløde påstande med AssertJ.
Lad os opsummere, hvad vi lærte fra dette blogindlæg.
Oversigt
Dette blogindlæg har lært os fem ting:
- Før vi kan skrive påstande med AssertJ, skal vi sikre, at
assertj-core
afhængighed findes fra klassestien. - Vi kan skrive påstande med AssertJ ved at bruge
static
metoder fororg.assertj.core.api.Assertions
klasse. - Hvis vi vil tilsidesætte beskrivelsesdelen af fejlmeddelelsen, der vises, når en påstand mislykkes, skal vi bruge enten
as()
ellerdescribedAs()
metoder forDescriptable
grænseflade. - Hvis vi vil tilsidesætte hele den fejlmeddelelse, der vises, når en påstand mislykkes, skal vi aktivere
overridingErrorMessage()
metode forAbstractAssert
klasse. - Vi kan skrive bløde påstande med AssertJ ved at bruge
org.assertj.core.api.SoftAssertions
klasse.