1. 概要

このチュートリアルでは、カスタムAssertJアサーションの作成について説明します。 AssertJの基本はここにあります。

簡単に言えば、カスタムアサーションを使用すると、独自のクラスに固有のアサーションを作成できるため、テストでドメインモデルをより適切に反映できます。

2. テスト中のクラス

このチュートリアルのテストケースは、Personクラスを中心に構築されます。

public class Person {
    private String fullName;
    private int age;
    private List<String> nicknames;

    public Person(String fullName, int age) {
        this.fullName = fullName;
        this.age = age;
        this.nicknames = new ArrayList<>();
    }

    public void addNickname(String nickname) {
        nicknames.add(nickname);
    }

    // getters
}

3. カスタムアサーションクラス

カスタムAssertJアサーションクラスの作成は非常に簡単です。 行う必要があるのは、AbstractAssertを拡張するクラスを宣言し、必要なコンストラクターを追加し、カスタムアサーションメソッドを提供することだけです。

アサーションクラスは、 AbstractAssert クラスを拡張して、isNotNullisEqualToなどのAPIの重要なアサーションメソッドにアクセスできるようにする必要があります。

Personのカスタムアサーションクラスのスケルトンは次のとおりです。

public class PersonAssert extends AbstractAssert<PersonAssert, Person> {

    public PersonAssert(Person actual) {
        super(actual, PersonAssert.class);
    }

    // assertion methods described later
}

AbstractAssert クラスを拡張するときは、2つの型引数を指定する必要があります。1つはメソッドチェーンに必要なカスタムアサーションクラス自体で、もう1つはテスト対象のクラスです。

アサーションクラスへのエントリポイントを提供するために、アサーションチェーンを開始するために使用できる静的メソッドを定義できます。

public static PersonAssert assertThat(Person actual) {
    return new PersonAssert(actual);
}

次に、PersonAssertクラスに含まれるいくつかのカスタムアサーションについて説明します。

最初のメソッドは、PersonのフルネームがString引数と一致することを確認します。

public PersonAssert hasFullName(String fullName) {
    isNotNull();
    if (!actual.getFullName().equals(fullName)) {
        failWithMessage("Expected person to have full name %s but was %s", 
          fullName, actual.getFullName());
    }
    return this;
}

次のメソッドは、Personageに基づいて成人であるかどうかをテストします。

public PersonAssert isAdult() {
    isNotNull();
    if (actual.getAge() < 18) {
        failWithMessage("Expected person to be adult");
    }
    return this;
}

最後に、ニックネームの存在を確認します。

public PersonAssert hasNickName(String nickName) {
    isNotNull();
    if (!actual.getNickNames().contains(nickName)) {
        failWithMessage("Expected person to have nickname %s", 
          nickName);
    }
    return this;
}

複数のカスタムアサーションクラスがある場合、すべての assertThat メソッドをクラスにラップして、各アサーションクラスに静的ファクトリメソッドを提供できます。

public class Assertions {
    public static PersonAssert assertThat(Person actual) {
        return new PersonAssert(actual);
    }

    // static factory methods of other assertion classes
}

上記のAssertionsクラスは、すべてのカスタムアサーションクラスへの便利なエントリポイントです。

このクラスの静的メソッドは同じ名前であり、パラメーターの種類によって互いに区別されます。

4. 動作中

次のテストケースは、前のセクションで作成したカスタムアサーションメソッドを示しています。 assertThat メソッドは、コアのAssertJ APIではなく、カスタムAssertionsクラスからインポートされることに注意してください。

hasFullNameメソッドの使用方法は次のとおりです。

@Test
public void whenPersonNameMatches_thenCorrect() {
    Person person = new Person("John Doe", 20);
    assertThat(person)
      .hasFullName("John Doe");
}

これは、isAdultメソッドを示すネガティブテストケースです。

@Test
public void whenPersonAgeLessThanEighteen_thenNotAdult() {
    Person person = new Person("Jane Roe", 16);

    // assertion fails
    assertThat(person).isAdult();
}

hasNicknameメソッドを示す別のテスト:

@Test
public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() {
    Person person = new Person("John Doe", 20);
    person.addNickname("Nick");

    // assertion will fail
    assertThat(person)
      .hasNickname("John");
}

5. アサーションジェネレータ

オブジェクトモデルに対応するカスタムアサーションクラスを作成することで、非常に読みやすいテストケースへの道が開かれます。

ただし、クラスが多数ある場合、それらすべてのカスタムアサーションクラスを手動で作成するのは面倒です。 ここで、AssertJアサーションジェネレータが機能します。

Mavenでアサーションジェネレーターを使用するには、pom.xmlファイルにプラグインを追加する必要があります。

<plugin>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-assertions-generator-maven-plugin</artifactId>
    <version>2.1.0</version>
    <configuration>
        <classes>
            <param>com.baeldung.testing.assertj.custom.Person</param>
        </classes>
    </configuration>
</plugin>

assertj-assertions-generator-maven-pluginの最新バージョンはここにあります。

上記のプラグインのclasses要素は、アサーションを生成するクラスをマークします。 プラグインの他の構成については、この投稿を参照してください。

AssertJアサーションジェネレーターは、ターゲットクラスのパブリックプロパティごとにアサーションを作成します。 各アサーションメソッドの具体的な名前は、フィールドまたはプロパティのタイプによって異なります。 アサーションジェネレータの完全な説明については、このリファレンスを確認してください。

プロジェクトのベースディレクトリで次のMavenコマンドを実行します。

mvn assertj:generate-assertions

フォルダに生成されたアサーションクラスが表示されるはずです目標 / Generated-test-sources/assertj-assertions。 例えば、 生成されたアサーションに対して生成されたエントリポイントクラスは次のようになります。

// generated comments are stripped off for brevity

package com.baeldung.testing.assertj.custom;

@javax.annotation.Generated(value="assertj-assertions-generator")
public class Assertions {

    @org.assertj.core.util.CheckReturnValue
    public static com.baeldung.testing.assertj.custom.PersonAssert
      assertThat(com.baeldung.testing.assertj.custom.Person actual) {
        return new com.baeldung.testing.assertj.custom.PersonAssert(actual);
    }

    protected Assertions() {
        // empty
    }
}

これで、生成されたソースファイルをテストディレクトリにコピーしてから、テスト要件を満たすカスタムアサーションメソッドを追加できます。

注意すべき重要な点の1つは、生成されたコードが完全に正しいとは限らないということです。 現時点では、ジェネレーターは完成品ではなく、コミュニティが取り組んでいます。

したがって、ジェネレーターを当然のことと考えるのではなく、私たちの生活を楽にするためのサポートツールとして使用する必要があります。

6. 結論

このチュートリアルでは、AssertJライブラリを使用して手動と自動の両方で読み取り可能なテストコードを作成するためのカスタムアサーションを作成する方法を示しました。

テスト対象のクラスの数が少ない場合は、手動による解決策で十分です。 それ以外の場合は、ジェネレーターを使用する必要があります。

そして、いつものように、すべての例とコードスニペットの実装はGitHubにあります。