web-dev-qa-db-ja.com

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

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

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

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

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

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

63
Patrick M

そして、古典的な方法で、質問を投稿した後、私が探していたものを見つけました。これにより、次の人が何と呼ばれているのかを最初に知ることなく、簡単に見つけられるようになりますマジックメソッドは、一見短い名前の as です。これは、AbstractAssertが実装する別のインターフェイスの一部です。 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ホームページには、機能が Soft Assertions セクションのasヘルパーの例を示すページを強調するまで、どちらのヘルパーも言及されていませんが、それが何をするのかを直接説明していません。

109
Patrick M

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に記載されています。

7
sleske

参考までに、これは新しいAssertJ Webサイトに文書化されています(まだ作成中ですが、既に有用な情報があります)。 https://assertj.github.io/doc/#assertj-core-assertion-description

2