Junit3時代はassertEquals
でアサーションしてJunit4になると当初はhamcrest
でアサーションしておりましたが最近はAssertJ
を使っております。
AssertJはFluent assertions for java
と紹介されているのですが、わかりやすく言うとテストをメソッドチェインで書いていくことができます。
例えば、文字列のテストをするときは以下のようにかけます。
String content = "Hello World.";
assertThat(content).startsWith("Hello")
.endsWith("World.")
.contains(" ");
この例は多少無理矢理感がありますがAssertJを使うと型によりアサーションが補完されるので導入当初からスムーズに書くことができます。
自分がよく使うのはリストのアサーションです。
リストのアサーションは場合によっては前処理でリストから要素を抽出したりとテストをするためのプログラムを書く必要があると思いますがAssertJのリストのアサーションだとかなり直感的にテストをかけます。
List actual = Utils.extractByGender(persons, "male");
assertThat(actual).extracting("name")
.hasSize(3)
.containsExactly("user1", "user3", "user5");
これはactualリストのPersonオブジェクトからnameプロパティの値を取り出してテストしています。
リストの要素は3かつcontainsExactlyで指定された内容化テストしています。
containsExactlyはExactlyと要素と順番の完全一致を要求します。
他にもいろいろあってcontainsは要素が含まれていれば大丈夫だし、containsOnlyは要素は一致、順番は不一致でも大丈夫というアサーションもあります。
含まれないことを要求するdoesnot系もあります。
また複数プロパティのテストもできます。
List actual = Utils.extractGteByAge(persons, 35);
assertThat(actual).extracting("name", "age")
.hasSize(3)
.containsExactly(
tuple("user3", 35),
tuple("user4", 35),
tuple("user5", 50));
こんな感じです。
自分がAssertJで一番好きなのは例外のテストです。
JUnitだと@Ruleを使って例外のテストをすると思います。
ガッチリとしたテストは書かずに例外が送出されインスタンスと簡単なメッセージのテストができればいい場合カジュアルに書きたいと思うことがあります。
その場合AssertJだと以下のようにかけます。
assertThatThrownBy(() -> { Utils.extractByGender(persons, null); })
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("gender must be not null or empty.");
assertThatThrownBy(() -> { Utils.extractByGender(persons, ""); })
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("gender must be not null or empty.");
assertThatThrownBy(() -> { Utils.extractByGender(persons, "root"); })
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("gender can be choice only male or female.");
例外を流れるように読んでいけるので自分は最近はこの書き方がしっくりきています。
他にもPath
やFile
のインスタンスを渡すと文字列の比較やfile or directoryなどをテストするアサーションがあります。
上記コードの詳細は以下に。
assertj-samples