1. 序章

この記事では、JUnit内で使用可能なアサーションについて詳しく説明します。

JUnit4からJUnit5への移行およびJUnit5 のガイドの記事に続いて、JUnit4およびJUnit5で使用可能なさまざまなアサーションについて詳しく説明します。

また、JUnit5でアサーションに加えられた機能強化についても説明します。

2. アサーション

アサーションは、テストでのアサーション条件をサポートするユーティリティメソッドです。 これらのメソッドには、JUnit4のAssert クラス、およびJUnit5のAssertionsoneからアクセスできます。

テストとアサーション自体の可読性を高めるために、それぞれのクラスを静的にimportすることを常にお勧めします。 このようにして、接頭辞としてクラスを表すことなく、アサーションメソッド自体を直接参照できます。

JUnit4で利用可能なアサーションの調査を始めましょう。

3. JUnit4のアサーション

このバージョンのライブラリでは、すべてのプリミティブタイプ、オブジェクト、および配列(プリミティブまたはオブジェクトのいずれか)でアサーションを使用できます。

アサーション内のパラメーターの順序は、期待値の後に実際の値が続きます。 オプションで、最初のパラメーターは、評価された条件のメッセージ出力を表すStringメッセージにすることができます。

assertThat アサーションの定義方法がわずかに異なるのは1つだけですが、これについては後で説明します。

assertEqualsから始めましょう。

3.1. assertEquals

assertEquals アサーションは、期待値と実際の値が等しいことを確認します。

@Test
public void whenAssertingEquality_thenEqual() {
    String expected = "Baeldung";
    String actual = "Baeldung";

    assertEquals(expected, actual);
}

アサーションが失敗したときに表示するメッセージを指定することもできます。

assertEquals("failure - strings are not equal", expected, actual);

3.2. assertArrayEquals

2つの配列が等しいことを表明する場合は、 assertArrayEquals:を使用できます。

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = {'J','u','n','i','t'};
    char[] actual = "Junit".toCharArray();
    
    assertArrayEquals(expected, actual);
}

両方の配列がnullの場合、アサーションはそれらを等しいと見なします。

@Test
public void givenNullArrays_whenAssertingArraysEquality_thenEqual() {
    int[] expected = null;
    int[] actual = null;

    assertArrayEquals(expected, actual);
}

3.3. assertNotNullおよびassertNull

オブジェクトがnullであるかどうかをテストする場合は、assertNullアサーションを使用できます。

@Test
public void whenAssertingNull_thenTrue() {
    Object car = null;
    
    assertNull("The car should be null", car);
}

逆に、オブジェクトがnullであってはならないことを表明したい場合は、assertNotNullアサーションを使用できます。

3.4. assertNotSameおよびassertSame

assertNotSame を使用すると、2つの変数が同じオブジェクトを参照していないかどうかを確認できます。

@Test
public void whenAssertingNotSameObject_thenDifferent() {
    Object cat = new Object();
    Object dog = new Object();

    assertNotSame(cat, dog);
}

それ以外の場合、2つの変数が同じオブジェクトを参照していることを確認する場合は、assertSameアサーションを使用できます。

3.5. assertTrueおよびassertFalse

特定の条件がtrueまたはfalseであることを確認する場合は、それぞれassertTrueアサーションまたはassertFalseアサーションを使用できます。 :

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue("5 is greater then 4", 5 > 4);
    assertFalse("5 is not greater then 6", 5 > 6);
}

3.6. 不合格

fail アサーションは、AssertionFailedErrorをスローするテストに失敗します。 これは、実際の例外がスローされたことを確認するため、または開発中にテストを失敗させたい場合に使用できます。

最初のシナリオでどのように使用できるか見てみましょう。

@Test
public void whenCheckingExceptionMessage_thenEqual() {
    try {
        methodThatShouldThrowException();
        fail("Exception not thrown");
    } catch (UnsupportedOperationException e) {
        assertEquals("Operation Not Supported", e.getMessage());
    }
}

3.7. assertThat

assertThat アサーションは、他のアサーションと比較してパラメーターの順序が逆になっているJUnit4の唯一のアサーションです。

この場合、アサーションには、オプションの失敗メッセージ、実際の値、およびMatcherオブジェクトがあります。

このアサーションを使用して、配列に特定の値が含まれているかどうかを確認する方法を見てみましょう。

@Test
public void testAssertThatHasItems() {
    assertThat(
      Arrays.asList("Java", "Kotlin", "Scala"), 
      hasItems("Java", "Kotlin"));
}

MatcherオブジェクトでのassertThatアサーションの強力な使用に関する追加情報は、Hamcrestでのテストで入手できます。

4. JUnit5アサーション

JUnit 5は、JUnit 4のアサーションメソッドの多くを維持しながら、Java8サポートを利用する新しいメソッドをいくつか追加しました。

また、このバージョンのライブラリでは、すべてのプリミティブタイプ、オブジェクト、、および配列(プリミティブまたはオブジェクトのいずれか)でアサーションを使用できます。

アサーションのパラメーターの順序が変更され、出力メッセージパラメーターが最後のパラメーターとして移動しました。 Java 8のサポートのおかげで、出力メッセージは Supplier になり、遅延評価が可能になります。

すでにJUnit4に相当するものがあったアサーションのレビューを始めましょう。

4.1. assertArrayEquals

assertArrayEquals アサーションは、期待される配列と実際の配列が等しいことを確認します。

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = { 'J', 'u', 'p', 'i', 't', 'e', 'r' };
    char[] actual = "Jupiter".toCharArray();

    assertArrayEquals(expected, actual, "Arrays should be equal");
}

配列が等しくない場合は、「配列は等しい」というメッセージが出力として表示されます。

4.2. assertEquals

2つのfloatsが等しいと主張したい場合は、単純なassertEquals主張を使用できます。

@Test
void whenAssertingEquality_thenEqual() {
    float square = 2 * 2;
    float rectangle = 2 * 2;

    assertEquals(square, rectangle);
}

ただし、実際の値が事前定義されたデルタによって期待値と異なることを表明する場合でも、 assertEquals を使用できますが、デルタ値を3番目のパラメーターとして渡す必要があります。

@Test
void whenAssertingEqualityWithDelta_thenEqual() {
    float square = 2 * 2;
    float rectangle = 3 * 2;
    float delta = 2;

    assertEquals(square, rectangle, delta);
}

4.3. assertTrueおよびassertFalse

assertTrue アサーションを使用すると、提供された条件がtrueであることを確認できます。

@Test
void whenAssertingConditions_thenVerified() {
    assertTrue(5 > 4, "5 is greater the 4");
    assertTrue(null == null, "null is equal to null");
}

ラムダ式のサポートのおかげで、 boolean 条件の代わりに、BooleanSupplierをアサーションに提供することができます。

assertFalse アサーションを使用して、BooleanSupplierの正しさをアサートする方法を見てみましょう。

@Test
public void givenBooleanSupplier_whenAssertingCondition_thenVerified() {
    BooleanSupplier condition = () -> 5 > 6;

    assertFalse(condition, "5 is not greater then 6");
}

4.4. assertNullおよびassertNotNull

オブジェクトがnullではないとアサートする場合は、assertNotNullアサーションを使用できます。

@Test
void whenAssertingNotNull_thenTrue() {
    Object dog = new Object();

    assertNotNull(dog, () -> "The dog should not be null");
}

逆に、 assertNull アサーションを使用して、実際がnullであるかどうかを確認できます。

@Test
public void whenAssertingNull_thenTrue() {
    Object cat = null;

    assertNull(cat, () -> "The cat should be null");
}

どちらの場合も、失敗メッセージはサプライヤーであるため、怠惰な方法で取得されます。

4.5. assertSameおよびassertNotSame

期待値と実際の値が同じObjectを参照していることを表明する場合は、assertSameアサーションを使用する必要があります。

@Test
void whenAssertingSameObject_thenSuccessfull() {
    String language = "Java";
    Optional<String> optional = Optional.of(language);

    assertSame(language, optional.get());
}

逆に、assertNotSameを使用できます。

4.6. 失敗

fail アサーションは、提供された失敗メッセージと根本的な原因でテストに失敗します。 これは、開発が完了していないときにテストにマークを付けるのに役立ちます。

@Test
public void whenFailingATest_thenFailed() {
    // Test not completed
    fail("FAIL - test not completed");
}

4.7. assertAll

JUnit 5で導入された新しいアサーションの1つは、assertAllです。

このアサーションにより、グループ化されたアサーションを作成できます。この場合、すべてのアサーションが実行され、それらの障害が一緒に報告されます。 詳細には、このアサーションは、MultipleFailureErrorのメッセージ文字列に含まれる見出しとExecutable。Streamを受け入れます。

グループ化されたアサーションを定義しましょう。

@Test
void givenMultipleAssertion_whenAssertingAll_thenOK() {
    Object obj = null;
    assertAll(
      "heading",
      () -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
      () -> assertEquals("java", "JAVA".toLowerCase()),
      () -> assertNull(obj, "obj is null")
    );
}

グループ化されたアサーションの実行は、実行可能ファイルの1つがブラックリストにある例外( OutOfMemoryError など)をスローした場合にのみ中断されます。

4.8. assertIterableEquals

assertIterableEquals は、期待される反復可能性と実際の反復可能性が完全に等しいことを表明します。

等しくなるためには、両方のイテレータが同じ順序で等しい要素を返す必要があり、等しくなるために2つのイテレータが同じタイプである必要はありません。

この考慮事項を考慮して、異なるタイプの2つのリスト(たとえば、LinkedListArrayList)が等しいと主張する方法を見てみましょう。

@Test
void givenTwoLists_whenAssertingIterables_thenEquals() {
    Iterable<String> al = new ArrayList<>(asList("Java", "Junit", "Test"));
    Iterable<String> ll = new LinkedList<>(asList("Java", "Junit", "Test"));

    assertIterableEquals(al, ll);
}

assertArrayEquals と同じように、両方の反復可能オブジェクトがnullの場合、それらは等しいと見なされます。

4.9. assertLinesMatch

assertLinesMatch は、Stringの期待されるリストが実際のリストと一致することを表明します。

このメソッドは、assertEqualsおよびassertIterableEqualsとは異なります。これは、予想されるラインと実際のラインのペアごとに、次のアルゴリズムを実行するためです。

  1. 期待される線が実際の線と等しいかどうかを確認します。 はいの場合、次のペアに進みます
  2. 期待される行を正規表現として扱い、 Stringmatches()メソッドを使用してチェックを実行します。 はいの場合、次のペアに進みます
  3. 予想される行が早送りマーカーであるかどうかを確認します。 はいの場合、早送りを適用し、ステップ1からアルゴリズムを繰り返します。

このアサーションを使用して、Stringの2つのリストに一致する行があることをアサーションする方法を見てみましょう。

@Test
void whenAssertingEqualityListOfStrings_thenEqual() {
    List<String> expected = asList("Java", "\\d+", "JUnit");
    List<String> actual = asList("Java", "11", "JUnit");

    assertLinesMatch(expected, actual);
}

4.10. assertNotEquals

assertEquals を補完するものとして、 assertNotEquals アサーションは、期待値と実際の値が等しくないことを表明します。

@Test
void whenAssertingEquality_thenNotEqual() {
    Integer value = 5; // result of an algorithm
    
    assertNotEquals(0, value, "The result cannot be 0");
}

両方がnullの場合、アサーションは失敗します。

4.11. assertThrows

単純さと読みやすさを向上させるために、新しい assertThrows アサーションを使用すると、実行可能ファイルが指定された例外タイプをスローした場合に、明確で簡単な方法でアサートできます。

スローされた例外をアサートする方法を見てみましょう。

@Test
void whenAssertingException_thenThrown() {
    Throwable exception = assertThrows(
      IllegalArgumentException.class, 
      () -> {
          throw new IllegalArgumentException("Exception message");
      }
    );
    assertEquals("Exception message", exception.getMessage());
}

例外がスローされない場合、または別のタイプの例外がスローされる場合、アサーションは失敗します。

4.12. assertTimeoutおよびassertTimeoutPreemptively

指定されたExecutableの実行が、指定された Timeout の前に終了することを表明する場合は、assertTimeoutアサーションを使用できます。

@Test
void whenAssertingTimeout_thenNotExceeded() {
    assertTimeout(
      ofSeconds(2), 
      () -> {
        // code that requires less than 2 minutes to execute
        Thread.sleep(1000);
      }
    );
}

ただし、 assertTimeout アサーションを使用すると、提供された実行可能ファイルは、呼び出し元のコードの同じスレッドで実行されます。 したがって、タイムアウトを超えても、サプライヤの実行が先制的に中止されることはありません。

実行可能ファイルがタイムアウトを超えたときに実行が中止されることを確認したい場合は、assertTimeoutPreemptivelyアサーションを使用できます。

どちらのアサーションも、実行可能ファイルの代わりに a ThrowingSupplier を受け入れることができます。これは、オブジェクトを返し、Throwableをスローする可能性のある一般的なコードブロックを表します。

5. 結論

このチュートリアルでは、JUnit4とJUnit5の両方で使用可能なすべてのアサーションについて説明しました。

新しいアサーションの導入とラムダのサポートにより、JUnit5で行われた改善について簡単に説明しました。

いつものように、この記事の完全なソースコードは、GitHubから入手できます。