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

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

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

  • JUnit 5 で基本的なアサーションを記述できる
  • アサーションが失敗したときに表示されるエラー メッセージをカスタマイズする方法を理解する
  • 複数のアサーションをアサーション グループとして実行する方法を理解する

始めましょう。

JUnit 5 でアサーションを書く

「標準」の JUnit 5 API を使用してアサーションを記述したい場合は、org.junit.jupiter.api.Assertions を使用する必要があります。 クラス。 static を提供します テスト中のシステムが実行された後、指定された条件が true であることを保証できるファクトリ メソッド。

これらのメソッドを詳しく見ていく前に、いくつかの基本的なルールを知っておく必要があります:

  • アサーションが失敗したときに表示されるカスタム エラー メッセージを指定する場合は、呼び出されたアサーション メソッドの最後のメソッド パラメータとしてこのメ​​ッセージを渡す必要があります。
  • 2 つの値 (またはオブジェクト) を比較する場合、これらの値 (またはオブジェクト) を、呼び出されたアサーション メソッドに、期待される値 (またはオブジェクト) と実際の値 (またはオブジェクト) の順序で渡す必要があります。

次に、Assertions を使用してアサーションを記述する方法を確認します。 クラス。 boolean のアサーションを書く方法を見つけることから始めましょう

ブール値のアサート

boolean であることを確認したい場合 値は true です 、 assertTrue() を使用する必要があります Assertions のメソッド クラス。つまり、次のアサーションを使用する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;

@DisplayName("Write assertions for booleans")
class BooleanAssertionTest {

    @Nested
    @DisplayName("When boolean is true")
    class WhenBooleanIsTrue {

        @Test
        @DisplayName("Should be true")
        void shouldBeTrue() {
            assertTrue(true);
        }
    }
}

boolean であることを確認したい場合 値は false です 、 assertFalse() を使用する必要があります Assertions のメソッド クラス。つまり、次のアサーションを使用する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;

@DisplayName("Write assertions for booleans")
class BooleanAssertionTest {

    @Nested
    @DisplayName("When boolean is false")
    class WhenBooleanIsFalse {

        @Test
        @DisplayName("Should be false")
        void shouldBeFalse() {
            assertFalse(false);
        }
    }
}

次に、オブジェクトが null であることを確認する方法を見つけます。 または null ではない .

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

オブジェクトが null であることを確認したい場合 、 assertNull() を使用する必要があります Assertions のメソッド クラス。つまり、次のアサーションを使用する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNull;

@DisplayName("Writing assertions for objects")
class ObjectAssertionTest {

    @Nested
    @DisplayName("When object is null")
    class WhenObjectIsNull {

        @Test
        @DisplayName("Should be null")
        void shouldBeNull() {
            assertNull(null);
        }
    }
}

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotNull;

@DisplayName("Writing assertions for objects")
class ObjectAssertionTest {

    @Nested
    @DisplayName("When object is not null")
    class WhenObjectIsNotNotNull {

        @Test
        @DisplayName("Should not be null")
        void shouldNotBeNull() {
            assertNotNull(new Object());
        }
    }
}

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

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

期待値 (またはオブジェクト) が実際の値 (またはオブジェクト) と等しいことを確認したい場合は、assertEquals() を使用する必要があります。 Assertions のメソッド クラス。たとえば、2 つの Integer を比較したい場合 オブジェクト、このアサーションを使用する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

@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() {
                assertEquals(EXPECTED, ACTUAL);
            }
        }
    }
}

期待値 (またはオブジェクト) が実際の値 (またはオブジェクト) と等しくないことを確認したい場合は、assertNotEquals() を使用する必要があります Assertions のメソッド クラス。たとえば、2 つの Integer を比較したい場合 オブジェクト、このアサーションを使用する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotEquals;

@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() {
                assertNotEquals(EXPECTED, ACTUAL);
            }
        }
    }
}

次に、オブジェクト参照のアサーションを記述する方法を確認します。

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

2 つのオブジェクトが同じオブジェクトを参照していることを確認するには、assertSame() を使用する必要があります。 Assertions のメソッド クラス。つまり、次のアサーションを使用する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertSame;

@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() {
            assertSame(EXPECTED, ACTUAL);
        }
    }
}

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotSame;

@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() {
            assertNotSame(EXPECTED, ACTUAL);
        }
    }
}

次に進み、2 つの配列が等しいことを確認する方法を見てみましょう。

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

2 つの配列が等しいことを確認したい場合は、assertArrayEquals() を使用する必要があります Assertions のメソッド クラス。たとえば、2 つの int を確認したい場合 配列が等しい場合、このアサーションを使用する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;

@DisplayName("Write assertions for arrays")
class ArrayAssertionTest {

    @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() {
            assertArrayEquals(EXPECTED, ACTUAL);
        }
    }
}

次に、2 つの iterable が等しいことを wen がどのように検証できるかを調べます。

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

2 つのイテラブルが完全に等しいことを確認したい場合は、assertIterableEquals() を使用する必要があります Assertions のメソッド クラス。たとえば、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.junit.jupiter.api.Assertions.assertIterableEquals;

@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() {
            assertIterableEquals(FIRST, SECOND);
        }
    }
}

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

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

テスト中のシステムによってスローされた例外のアサーションを書きたい場合は、 assertThrows() を使用する必要があります Assertions のメソッド クラス。このメソッドは、次のメソッド パラメータを取ります:

  • A Class 予想される例外のタイプを指定するオブジェクト
  • Executable テスト中のシステムを呼び出すオブジェクト
  • オプションのエラー メッセージ。

たとえば、テスト対象のシステムが NullPointerException をスローすることを確認したい場合 、アサーションは次のようになります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertThrows;

@DisplayName("Writing assertions for exceptions")
class ExceptionAssertionTest {

    @Test
    @DisplayName("Should throw the correct exception")
    void shouldThrowCorrectException() {
        assertThrows(
                NullPointerException.class,
                () -> { throw new NullPointerException(); }
        );
    }
}

assertThrows() メソッドはスローされた例外オブジェクトを返します。スローされた例外に対して追加のアサーションを記述することもできます。たとえば、スローされた例外に正しいメッセージがあることを確認したい場合は、次のアサーションを使用できます:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@DisplayName("Writing assertions for exceptions")
class ExceptionAssertionTest {

    @Test
    @DisplayName("Should throw an exception that has the correct message")
    void shouldThrowAnExceptionWithCorrectMessage() {
        final NullPointerException thrown = assertThrows(
                NullPointerException.class,
                () -> { throw new NullPointerException("Hello World!"); }
        );
        assertEquals("Hello World!", thrown.getMessage());
    }
}

一方、テスト対象のシステムが例外をスローした場合にテスト メソッドが失敗したとしても、テストされたコードによって例外がスローされないことを明示的に表明したい場合があります。この場合、assertDoesNotThrow() を使用する必要があります。 Assertions のメソッド クラス。テスト中のシステムによって例外がスローされないことを確認したい場合は、次の 2 つのオプションのいずれかを使用できます。

最初 テスト中のシステムから返された値のアサーションを書きたくない場合は、次のメソッド パラメータを assertDoesNotThrow() に渡す必要があります。 メソッド:

  • Executable テスト中のシステムを呼び出すオブジェクト
  • オプションのエラー メッセージ。

たとえば、テスト対象のシステムが例外をスローしないことを確認する場合、アサーションは次のようになります。

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

@DisplayName("Writing assertions for exceptions")
class ExceptionAssertionTest {

    @Test
    @DisplayName("Should not throw an exception")
    void shouldNotThrowException() {
        assertDoesNotThrow(() -> {});
    }
}

2番目 、テスト中のシステムによって返された値のアサーションを書きたい場合は、次のメソッド パラメータを assertDoesNotThrow() に渡す必要があります。 メソッド:

  • A ThrowingSupplier テスト対象のシステムを呼び出す (そして戻り値を返す) オブジェクト。
  • オプションのエラー メッセージ。

たとえば、テスト対象のシステムが例外をスローしないことを確認し、かつテスト対象のシステムが正しいメッセージを返すことを確認する場合、アサーションは次のようになります。

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Writing assertions for exceptions")
class ExceptionAssertionTest {

    @Test
    @DisplayName("Should not throw an exception")
    void shouldNotThrowException() {
        String message = assertDoesNotThrow(() -> { return "Hello World!"; } );
        assertEquals("Hello World!", message);
    }
}

次に、テスト中のシステムの実行時間に関するアサーションを作成する方法を見つけます。

テスト中のシステムの実行時間に関するアサーションの記述

指定されたタイムアウトを超える前にテスト中のシステムの実行が完了していることを確認したい場合は、 assertTimeout() を使用できます と assertTimeoutPreemptively() Assertions のメソッド クラス。これらのメソッドは両方とも、次のメソッド パラメーターを取ります。

  • A Duration タイムアウトを指定するオブジェクト
  • Executable または ThrowingSupplier テスト中のシステムを呼び出すオブジェクト
  • 指定されたタイムアウトを超えた場合に表示されるオプションのエラー メッセージ

これら 2 つの方法はよく似ていますが、決定的な違いが 1 つあります。この違いについては、次で説明します:

  • assertTimeout() を使用する場合 メソッド、提供された Executable または ThrowingSupplier それを呼び出すコードと同じスレッドで実行されます。また、タイムアウトを超えても、このメソッドは実行を中止しません。
  • assertTimeoutPreemptively() を使用する場合 メソッド、提供された Executable または ThrowingSupplier それを呼び出すコードとは別のスレッドで実行されます。また、タイムアウトを超えると、このメソッドは実行を中止します。

ご覧のとおり、次の 2 つのオプションのいずれかを使用して、指定されたタイムアウトを超える前にテスト対象のシステムの実行が完了したことを確認できます。

最初 、タイムアウトを超えても実行が中止されないようにする場合は、 assertTimeout() を使用する必要があります Assertions のメソッド クラス。たとえば、テスト対象のシステムが「Hello world!」というメッセージを返すことを確認したい場合です。指定されたタイムアウト (50ms) を超える前に、次のようなアサーションを作成する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.Duration;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTimeout;

@DisplayName("Writing assertions for the execution time of the system under test")
class TimeoutAssertionTest {

    @Test
    @DisplayName("Should return the correct message before timeout is exceeded")
    void shouldReturnCorrectMessageBeforeTimeoutIsExceeded() {
        final String message = assertTimeout(Duration.ofMillis(50), () -> {
            Thread.sleep(20);
            return "Hello World!";
        });
        assertEquals("Hello World!", message);
    }
}

2番目 、タイムアウトを超えた場合に実行を中止したい場合は、 assertTimeoutPreemptively() を使用する必要があります Assertions のメソッド クラス。たとえば、テスト対象のシステムが「Hello world!」というメッセージを返すことを確認したい場合です。指定されたタイムアウト (50ms) を超える前に、次のようなアサーションを作成する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.Duration;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;

@DisplayName("Writing assertions for the execution time of the system under test")
class TimeoutAssertionTest {

    @Test
    @DisplayName("Should return the correct message before timeout is exceeded")
    void shouldReturnCorrectMessageBeforeTimeoutIsExceeded() {
        final String message = assertTimeoutPreemptively(Duration.ofMillis(50), () -> {
            Thread.sleep(20);
            return "Hello World!";
        });
        assertEquals("Hello World!", message);
    }
}

JUnit 5 で基本的なアサーションを記述できるようになりました。次に進み、アサーションが失敗した場合に JUnit 5 によって表示されるエラー メッセージをカスタマイズする方法を見てみましょう。

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

アサーションが失敗したときに表示されるカスタム エラー メッセージを指定する場合は、呼び出されたアサーション メソッドの最後のメソッド パラメータとしてこのメ​​ッセージを渡す必要があります。このメッセージは、次の 2 つのオプションのいずれかを使用して作成できます。

最初 、新しい String を作成できます オブジェクトを取得し、呼び出されたアサーション アサーション メソッドの最後のメソッド パラメータとしてこのオブジェクトを渡します。エラー メッセージにパラメーターがない場合は、これが適切な選択です。たとえば、boolean を検証するアサーションにカスタム エラー メッセージを提供したい場合 値は false です 、次のようなアサーションを作成する必要があります:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;

@DisplayName("Write assertions for booleans")
class BooleanAssertionTest {

    @Nested
    @DisplayName("When boolean is false")
    class WhenBooleanIsFalse {

        @Test
        @DisplayName("Should be false")
        void shouldBeFalse() {
            assertFalse(false, "The boolean is not false");
        }
    }
}

2番目 、メッセージ サプライヤーを作成できます (Supplier )、呼び出されたアサーション メソッドの最後のメソッド パラメータとしてこのサプライヤを渡します。このアプローチを使用すると、JUnit 5 は実際のエラー メッセージをのみ作成します。 私たちの主張が失敗した場合。そのため、パラメーターを持つ「複雑な」エラー メッセージを作成する場合は、これが適切な選択です。

たとえば、特定のキーがマップに含まれていることを確認するアサーションにカスタム エラー メッセージを提供する場合、次のようなアサーションを作成する必要があります。

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertTrue;

@DisplayName("Writing assertions for maps")
class MapAssertionTest {

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

    @Test
    @DisplayName("Should contain the correct key")
    void shouldContainCorrectKey() {
        assertTrue(
                map.containsKey(KEY), 
                () -> String.format("The map doesn't contain the key: %s", KEY)
        );
    }
}

次に、JUnit 5 でアサーションをグループ化する方法を確認します。

アサーションのグループ化

複数のアサーションを必要とする状態のアサーションを記述する必要がある場合は、assertAll() を使用してアサーションをグループ化できます。 Assertions のメソッド クラス。このメソッドは、次のメソッド パラメータを取ります:

  • アサートされた状態を識別するオプションの見出し。
  • 配列、Collection 、または Stream Executable の アサーションを呼び出すオブジェクト。

assertAll() を呼び出すと、 メソッドでは、指定されたすべてのアサーションを呼び出し、すべてのアサーションが実行された後にすべてのアサーションの失敗を報告します。

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 を確認する必要があります。 オブジェクトの姓名が正しいこと。つまり、次のようなアサーションを作成する必要があります:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("Group multiple assertions")
class GroupAssertionsTest {

    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() {
        assertAll("name",
                () -> assertEquals(FIRST_NAME, 
                        person.getFirstName(), 
                        "The first name is incorrect"
                ),
                () -> assertEquals(LAST_NAME, 
                        person.getLastName(), 
                        "The last name is incorrect"
                )
        );
    }
}

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

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

まとめ

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

  • 「標準」の JUnit 5 API を使用してアサーションを記述したい場合は、org.junit.jupiter.api.Assertions を使用する必要があります。 クラス。
  • パラメータのないカスタム エラー メッセージを指定する場合は、新しい String を作成する必要があります オブジェクトを取得し、呼び出されたアサーション メソッドの最後のメソッド パラメータとしてこのオブジェクトを渡します。
  • パラメータを持つ「複雑な」エラー メッセージを指定する場合は、メッセージ サプライヤ (Supplier) を作成する必要があります。 )、呼び出されたアサーション メソッドの最後のメソッド パラメータとしてこのサプライヤを渡します。
  • 複数のアサーションを必要とする状態のアサーションを作成する必要がある場合は、assertAll() を使用してアサーションをグループ化できます。 Assertions のメソッド クラス。

Java タグ