AssertJ assertThatにカスタムメッセージを追加できますか?


92

主にHamcrestマッチャーでJUnitアサーションを使用するテストスイートがあります。私たちのチームの1人は、AssertJの実験を開始し、その構文、柔軟性、および宣言型性で人々に感銘を与えました。JUnitが提供する、AssertJに相当するものが見つからない機能が1つあります。それは、カスタムのアサート失敗メッセージを追加することです。

人間が読みやすいように作成されておらず、ランダムに見えるIDまたはUUIDを持つオブジェクトを比較することがよくあり、それらに含まれるデータによってそれらが何であるかを判断することは不可能です。悲しいことに、これはコードベースにとって避けられない状況です。コードベースが果たす目的の一部は、必ずしもそれが何であるかを理解せずに、他のサービス間でデータをマッピングすることです。

JUnitでは、assertThatメソッドはString reasonパラメーターの前にパラメーターを持つバージョンを提供しますMatcher<T>。これにより、人間にとっての比較の意味など、問題に光を当てる短いデバッグ文字列を追加するのは簡単です。

一方、AssertJは、何らかの形式のインターフェイスAssertまたはその多くの実装クラスの1つを返す無数の異なる汎用static assertThatメソッドを提供します。このインターフェースは、失敗に含まれるカスタムメッセージを設定する標準的な方法を提供しません。

メッセージを追加するすべてのアサーションタイプに対してカスタムアサーションクラス作成せずに、AssertJ APIまたはその拡張機能の1つからこの機能を取得する方法はありますか?

回答:


139

そして、古典的な方法で、私は質問を投稿した直後に私が探していたものを見つけました。うまくいけば、これにより、最初にそれが何と呼ばれているのかを知らなくても、次の人が見つけやすくなります。魔法のメソッドは一見短い名前でasAbstractAssert実装する別のインターフェースの一部です。基本のAssertインターフェースではなく、Descriptableです。

public S as(String description, Object... args)

String.format(String, Object...)構文をサポートするこのオブジェクトの説明を設定します。
例:

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description with as() method or describedAs(), it supports String format args
  assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("[check Frodo's age] expected:<[33]> but was:<[50]>");
}

catchブロック内の引用符で囲まれた文字列はhasMessage、アサーションが失敗した場合に単体テストの出力ログに表示されるものです。


質問にリンクされてfailWithMessageいるカスタムアサーションページのヘルパーに気づいたことで、これを見つけました。そのメソッドのJavaDocは、保護されていることを示しているため、呼び出し元がカスタムメッセージを設定するために使用することはできません。ただし、asヘルパーについては言及されています。

さらに、このメソッドは、で設定された説明、as(String, Object...)またはユーザーがで定義したエラーメッセージを上書きしたものを尊重しoverridingErrorMessage(String, Object...)ます。

...とoverridingErrorMessage完全に標準AssertJの置き換えヘルパー、expected: ... but was:...提供された新しい文字列を使用してメッセージを。

AssertJホームページでは、機能がハイライトページに表示されるまで、どちらのヘルパーについても言及していません。このページにasは、ソフトアサーションセクションのヘルパーの例が示されていますが、その機能については直接説明されていません。


24

Patrick Mの回答に別のオプションを追加するには:

を使用する代わりにDescriptable.as、次を使用することもできますAbstractAssert.withFailMessage()

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description via withFailMessage(), supports String format args
  assertThat(frodo.getAge()).
    withFailMessage("Frodo's age is wrong: %s years, difference %s years",
      frodo.getAge(), frodo.getAge()-33).
    isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("Frodo's age is wrong: 50 years, difference 17 years");
}

使用Descriptable.asすることとの違いは、カスタムメッセージ完全に制御できることです。「期待される」と「あった」というものはありません。

これは、テストされている実際の値が表示に役立たない場合に役立ちます。この方法では、代わりに他の、場合によっては計算された値を表示するか、まったく表示しないことができます。


と同様にDescriptable.as、実際のアサーションのwithFailMessage() 前に呼び出す必要があることに注意してください。そうしないと、アサーションが最初に起動するため、機能しません。これはJavadocに記載されています。


4
「実際のアサーションの前にwithFailMessage()を呼び出す必要があります」ありがとう、これは私をつまずかせました。呼び出しの順序withFailMessage。私はAssertJが好きですが、これは最悪です。
アビジット・サルカール


0

as()AssertJの組み込みメソッドを使用します。例えば:

 assertThat(myTest).as("The test microservice is not active").isEqualTo("active");
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.