Java >> Java チュートリアル >  >> Tag >> assert

JUnit 5 チュートリアル:AssertJ を使用したアサーションの記述

このブログ投稿では、AssertJ を使用してアサーションを作成する方法について説明します。このブログ投稿を終えたら、次のことを行います。

  • Maven と Gradle で必要な依存関係を取得できる
  • AssertJ を使用して基本的なアサーションを記述する方法を理解する
  • アサーションが失敗したときに表示されるエラー メッセージをカスタマイズする方法を理解する
  • AssertJ でソフト アサーションを記述できる

始めましょう。

必要な依存関係を取得する

AssertJ でアサーションを書く前に、 assertj-core 依存関係 (バージョン 3.21.0) がクラスパスから見つかりました。

Maven を使用している場合は、assertj-core を追加する必要があります test への依存 範囲。これを行うには、次のスニペットを dependencies に追加します pom.xml のセクション ファイル:

<dependency>
	<groupId>org.assertj</groupId>
	<artifactId>assertj-core</artifactId>
	<version>3.21.0</version>
	<scope>test</scope>
</dependency>

Gradle を使用している場合は、assertj-core を追加する必要があります testImplementation への依存 依存関係の構成。これを行うには、build.gradle に次のスニペットを追加します。 ファイル:

dependencies {
    testImplementation(
            'org.assertj:assertj-core:3.21.0'
    )
}

この依存関係をクラスパスに追加した後、AssertJ でアサーションを記述できます。どうすればできるか見てみましょう。

AssertJ によるアサーションの記述

AssertJ でアサーションを書きたい場合、 static assertThat() を使用する必要があります org.assertj.core.api.Assertions のメソッド クラス。このメソッドを呼び出すときは、次の 2 つのことを知っておく必要があります。

  • assertThat() メソッドは、実際の値またはオブジェクトをメソッド パラメータとして受け取ります。
  • Assertions() クラスはメソッドのオーバーロードと assertThat() によって返されるオブジェクトの型を使用します メソッドは、そのメソッドに渡される引数の型に依存します。

assertThat() を呼び出した後 メソッドを使用すると、返されたアサーション オブジェクトを使用してアサーションを記述できます。また、AssertJ は流暢な API を提供するため、各アサーション メソッドは使用されたアサーション オブジェクトへの参照を返します。これは、別のアサーション メソッドを呼び出すだけでアサーションを連鎖できることを意味します。

次に、AssertJ を使用してアサーションを作成する方法を示すいくつかの例を見ていきます。

ブール値のアサート

boolean であることを確認したい場合 値は true です 、 isTrue() を呼び出してアサーションを作成する必要があります AbstractBooleanAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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();
        }
    }
}

boolean であることを確認したい場合 値は false です 、 isFalse() を呼び出してアサーションを書かなければなりません AbstractBooleanAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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();
        }
    }
}

オブジェクトが null であることを確認する方法を見てみましょう。 または null ではない .

オブジェクトが Null であるか、または Null ではないことをアサートする

オブジェクトが null であることを確認したい場合 、 isNull() を呼び出してアサーションを書かなければなりません AbstractAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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();
        }
    }
}

オブジェクトが null でないことを確認したい場合 、 isNotNull() を呼び出してアサーションを作成する必要があります AbstractAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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();
        }
    }
}

次に、2 つのオブジェクト (または値) が等しいか等しくないかを確認する方法を見つけます。

2 つのオブジェクトまたは値が等しいと主張する

期待値 (またはオブジェクト) が実際の値 (またはオブジェクト) と等しいことを確認したい場合は、isEqualTo() のいずれかを呼び出してアサーションを記述する必要があります。 AbstractAssert のメソッド クラスまたは isEqualByComparingTo() AbstractComparableAssert のメソッド クラス。これらの方法の違いについては、以下で説明します:

  • isEqualTo() メソッドは equals() を呼び出します メソッド。
  • isEqualByComparingTo() メソッドは Comparable の compareTo() メソッドを呼び出します インターフェース。

たとえば、2 つの整数が等しいことを確認したい場合は、次のようなアサーションを使用する必要があります:

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);
            }
        }
    }
}

期待値 (またはオブジェクト) が実際の値 (またはオブジェクト) と等しくないことを確認したい場合は、isNotEqualTo() のいずれかを呼び出してアサーションを記述する必要があります。 AbstractAssert のメソッド クラスまたは isNotEqualByComparingTo() AbstractComparableAssert のメソッド クラス。これらのメソッドは isEqualTo() と同じ方法で実装されています と isEqualByComparingTo() メソッド。

たとえば、2 つの整数が等しくないことを確認したい場合は、次のようなアサーションを使用する必要があります。

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);
            }
        }
    }
}

オブジェクト参照のアサーションを記述する方法を見ていきましょう。

オブジェクト参照のアサート

2 つのオブジェクトが同じオブジェクトを参照していることを確認したい場合は、isSameAs() を呼び出してアサーションを記述する必要があります。 AbstractAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
        }
    }
}

2 つのオブジェクトが同じオブジェクトを参照しないようにしたい場合は、isNotSameAs() を呼び出してアサーションを記述する必要があります。 AbstractAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
        }
    }
}

次に、2 つの配列が等しいか等しくないかを確認する方法を見つけます。

2 つの配列が等しいと主張する

2 つの配列が等しいことを確認したい場合は、isEqualTo() を呼び出してアサーションを記述する必要があります。 AbstractArrayAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
            }
        }
    }
}

2 つの配列が等しくないことを確認したい場合は、isNotEqualTo() を呼び出してアサーションを記述する必要があります。 AbstractArrayAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
            }
        }
    }
}

次に進み、イテラブルのアサーションを記述する方法を見てみましょう。

イテラブルのアサーションを書く

Iterable のサイズを検証するアサーションを書きたい場合 正解です。次の 3 つのオプションのいずれかを使用できます。

  • イテラブルが空であることを確認したい場合は、isEmpty() を呼び出してアサーションを記述できます。 AbstractIterableAssert のメソッド クラス。
  • イテラブルが空でないことを確認したい場合は、isNotEmpty() を呼び出してアサーションを記述できます。 AbstractIterableAssert のメソッド クラス。
  • イテラブルのサイズが正しいことを確認したい場合は、hasSize() を呼び出してアサーションを記述できます。 AbstractIterableAssert のメソッド クラス。

たとえば、リストに 2 つの要素が含まれていることを確認する場合は、次のようなアサーションを使用する必要があります。

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);
        }
    }
}

iterable が指定された順序で期待される要素のみを含むようにしたい場合は、containsExactly() を使用してアサーションを記述する必要があります。 AbstractIterableAssert のメソッド クラス。たとえば、リストに正しい要素が指定された順序で含まれていることを確認する場合は、次のアサーションを使用する必要があります:

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);
        }
    }
}

イテラブルに任意の順序で期待される要素のみが含まれていることを確認したい場合は、containsExactlyInAnyOrder() を使用してアサーションを記述する必要があります。 AbstractIterableAssert のメソッド クラス。たとえば、リストに正しい要素が任意の順序で含まれていることを確認したい場合は、次のアサーションを使用する必要があります:

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);
        }
    }
}

iterable に指定された要素が含まれていることを確認したい場合は、containsOnlyOnce() を使用してアサーションを記述する必要があります。 AbstractIterableAssert のメソッド クラス。たとえば、リストに Object が含まれていることを確認したい場合 first というフィールドに保存されます 、このアサーションを使用する必要があります:

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);
        }
    }
}

iterable に指定された要素が含まれていないことを確認したい場合は、doesNotContain() を使用してアサーションを記述する必要があります。 AbstractIterableAssert のメソッド クラス。たとえば、指定したオブジェクトがリストに含まれていないことを確認する場合は、次のアサーションを使用する必要があります:

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());
        }
    }
}

2 つのイテラブルが完全に等しいことを確認したい場合は、isEqualTo() を使用してアサーションを記述する必要があります。 AbstractAssert のメソッド クラス。たとえば、2 つの Integer を確認したい場合 リストは非常に等しいので、次のアサーションを使用する必要があります:

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);
        }
    }
}

次に、マップのアサーションを記述する方法を確認します。

マップのアサーションの記述

マップに指定されたキーが含まれていることを確認したい場合は、containsKey() を呼び出してアサーションを記述する必要があります。 AbstractMapAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
        }
    }
}

指定したキーがマップに含まれていないことを確認したい場合は、doesNotContainKey() を呼び出してアサーションを記述する必要があります。 AbstractMapAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
        }
    }
}

マップに指定されたエントリが含まれていることを確認したい場合は、containsEntry() を呼び出してアサーションを記述する必要があります。 AbstractMapAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
        }
    }
}

指定されたエントリがマップに含まれていないことを確認したい場合は、doesNotContainEntry() を呼び出してアサーションを記述する必要があります。 AbstractMapAssert のメソッド クラス。つまり、次のようなアサーションを使用する必要があります:

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);
        }
    }
}

次に進み、テスト中のシステムによってスローされた例外に対するアサーションを記述する方法を見てみましょう。

例外に対するアサーションの記述

テスト中のシステムによってスローされた例外のアサーションを書きたい場合は、次の 2 つのオプションのいずれかを使用できます。

最初static assertThatThrownBy() を使用できます org.assertj.core.api.Assertions のメソッド クラス。この方法を使用する場合、次の 2 つのことを知っておく必要があります。

  • ThrowingCallable かかります オブジェクトをメソッド パラメータとして指定します。このオブジェクトは、テスト中のシステムを呼び出します。
  • AbstractThrowableAssert を返します 物体。テスト中のシステムによってスローされた例外のアサーションを記述するときは、このオブジェクトを使用する必要があります。

このアプローチを使用してアサーションを記述する方法を示す 2 つの例を見てみましょう。

テスト対象のシステムが予想される例外をスローすることを確認したい場合は、isExactlyInstanceOf() を使用してアサーションを記述する必要があります。 AbstractThrowableAssert のメソッド クラス。たとえば、テスト対象のシステムが NullPointerException をスローすることを確認したい場合 、次のようなアサーションを作成する必要があります:

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);
            }
        }
    }
}

テスト対象のシステムが予期したメッセージを持つ例外をスローすることを確認したい場合は、hasMessage() を使用してアサーションを記述する必要があります。 AbstractThrowableAssert のメソッド クラス。たとえば、テスト対象のシステムが「Hello World!」というメッセージを含む例外をスローすることを確認したい場合、次のようなアサーションを作成する必要があります:

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!");
            }
        }
    }
}

2番目 static catchThrowable() を使用して、スローされた例外をキャッチできます。 org.assertj.core.api.Assertions のメソッド クラス。このメソッドは、次に説明する 2 つのメソッド パラメータを取ることができます:

  • A ThrowingCallable テスト中のシステムを呼び出すオブジェクト
  • Class 予想される例外のタイプを指定するオブジェクト。これはオプションのパラメーターです。これを catchThrowable() に渡すと、 メソッドで、返される例外オブジェクトのタイプを指定します。このメソッド パラメータを省略すると、catchThrowable() メソッドは Throwable を返します オブジェクト。

このアプローチを使用してアサーションを記述する方法を示す 2 つの例を見てみましょう。

テスト対象のシステムが予想される例外をスローすることを確認したい場合は、isExactlyInstanceOf() を使用してアサーションを記述する必要があります。 AbstractThrowableAssert のメソッド クラス。たとえば、テスト対象のシステムが NullPointerException をスローすることを確認したい場合 、次のようなアサーションを作成する必要があります:

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);
            }
        }
    }
}

テスト対象のシステムが予期したメッセージを持つ例外をスローすることを確認したい場合は、hasMessage() を使用してアサーションを記述する必要があります。 AbstractThrowableAssert のメソッド クラス。たとえば、テスト対象のシステムが「Hello World!」というメッセージを含む例外をスローすることを確認したい場合、次のようなアサーションを作成する必要があります:

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!");
            }
        }
    }
}

次に、Optional のアサーションをどのように記述できるかを調べます。 オブジェクト。

オプション オブジェクトのアサーションの記述

Optional であることを確認したい場合 isEmpty() を呼び出してアサーションを記述する必要があります。 AbstractOptionalAssert のメソッド クラス。つまり、次のようなアサーションを作成する必要があります:

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();
        }
    }
}

Optional であることを確認したい場合 isNotEmpty() を呼び出してアサーションを記述する必要があります。 AbstractOptionalAssert のメソッド クラス。つまり、次のようなアサーションを作成する必要があります:

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();
        }
    }
}

Optional であることを確認したい場合 contains() を呼び出してアサーションを記述する必要があります。 AbstractOptionalAssert のメソッド クラス。つまり、次のようなアサーションを作成する必要があります:

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);
        }
    }
}

次に進み、アサーションが失敗したときに表示されるカスタム エラー メッセージを指定する方法を見てみましょう。

カスタム エラー メッセージの提供

AssertJ のエラー メッセージは非常に優れていますが、アサーションによって適用されるビジネス ルールを強調したい場合があります。これを行う場合、次の 2 つのオプションのいずれかを使用して、カスタム エラー メッセージを提供できます。

  • エラー メッセージの説明部分をオーバーライドする場合は、as() のいずれかを呼び出す必要があります。 または describedAs() Descriptable のメソッド インターフェース。
  • エラー メッセージ全体をオーバーライドする場合は、overridingErrorMessage() を呼び出す必要があります。 AbstractAssert のメソッド クラス。

これらのメソッドはすべて、以下で説明する 2 つのメソッド パラメータを取ることができます:

  • A String エラーメッセージを含むオブジェクト。動的なエラー メッセージを提供する場合は、String.format() でサポートされている形式を使用できます。 メソッド。
  • オプションの Object エラーメッセージのパラメータを含む配列。このメソッド パラメータは String.format() に渡されます 実際のエラー メッセージを作成するメソッド。そのため、静的エラー メッセージを使用する場合、このメソッド パラメータを指定する必要はありません。

これらのオプションの違いを示す 2 つの例を見てみましょう。

最初 、表示されたエラー メッセージの説明部分のみをオーバーライドする場合は、次のようなアサーションを記述する必要があります。

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();
        }
    }
}

アサーションが失敗すると、次のようなエラー メッセージが表示されます。

org.opentest4j.AssertionFailedError: [The boolean is not false] 
Expecting: <true> to be equal to: <false> but was not.
Expected :false
Actual   :true

2番目 、エラー メッセージ全体をオーバーライドする場合は、次のようなアサーションを記述する必要があります。

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();
        }
    }
}

アサーションが失敗すると、次のようなエラー メッセージが表示されます。

java.lang.AssertionError: The boolean is not false

次に進み、AssertJ を使用してソフト アサーションを作成する方法を見てみましょう。

ソフト アサーションの記述

複数のアサーションを必要とする状態のアサーションを作成する必要がある場合は、すべてのアサーションを実行し、すべてのアサーションが実行された後にすべてのアサーションの失敗を報告することをお勧めします。ソフト アサーションを使用して、AssertJ でこれを行うことができます。

Person を検証するアサーションを書かなければならないとしましょう。 オブジェクトに正しい名前があります。 Person のソースコード クラスは次のようになります:

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;
    }
}

お分かりのように、人が正しい名前を持っていることを確認したい場合は、アサートされた Person を確認する必要があります。 オブジェクトの姓名が正しいこと。次の手順に従ってアサーションを記述できます。

<オール>
  • 新しい SoftAssertions を作成します オブジェクト。
  • Person であることを確認してください オブジェクトの名が正しい
  • Person であることを確認してください オブジェクトは正しい姓を持っています。
  • assertAll() を呼び出して、すべてのアサーションを実行します SoftAssertions の方法 クラス。このメソッドは、指定されたすべてのアサーションを実行し、これらのアサーションの実行後にアサーションの失敗を報告します。
  • 必要なソフト アサーションを記述した後、テスト クラスのソース コードは次のようになります。

    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();
        }
    }
    

    AssertJ で基本的なアサーションを記述し、アサーションが失敗したときに表示されるカスタム エラー メッセージを提供し、AssertJ でソフト アサーションを記述できるようになりました。

    このブログ投稿から学んだことをまとめましょう。

    まとめ

    このブログ投稿から 5 つのことがわかりました:

    • AssertJ でアサーションを書く前に、assertj-core 依存関係がクラスパスから見つかりました。
    • static を使用して、AssertJ でアサーションを記述できます。 org.assertj.core.api.Assertions のメソッド クラス。
    • アサーションが失敗したときに表示されるエラー メッセージの説明部分をオーバーライドする場合は、as() のいずれかを使用する必要があります。 または describedAs() Descriptable のメソッド インターフェース。
    • アサーションが失敗したときに表示されるエラー メッセージ全体をオーバーライドする場合は、overridingErrorMessage() を呼び出す必要があります。 AbstractAssert のメソッド クラス。
    • org.assertj.core.api.SoftAssertions を使用して、AssertJ でソフト アサーションを記述できます。 クラス。

    Java タグ