JUnitでの検証メソッドについて


先日、遅ればせながらJUnit5を使ってみたら、なんとassertThatがいなくなっていました。
「アサーションは利用者が好きなものを使ってね」という方針のようです。

そこで、JUnitで使う検証メソッドについて、
今まで使ってきたものを含めて、利用候補を考えてみます。

org.junit.Assert.assertEquals

伝統的なメソッド。新入社員時代にはお世話になりました。
assertThatがいるので今はあまり使われていない(はず)。

@Test
public void test01() {
    int sum = add(30, 70);
    assertEquals(100, sum);
}

期待値と実測値が分かり辛い

Javadocによると左が期待値で右が実測値らしいですが、よく忘れます。
チーム開発すると何人かは逆に書いたりして、後から混乱を招くことも。

「どっちでもいいじゃん」という人もいるかも知れませんが、期待値と実測値が逆になったエラーメッセージは個人的には気持ち悪いです。
java.lang.AssertionError: expected:<0> but was:<100>

一致判定にしか対応できない

メソッド名がequalsなので当然と言えば当然です。
一致判定以外のケースでは後述するassertTrueを使っているはず。

org.junit.Assert.assertTrue

assertEqualsと同じく伝統的なメソッド。こちらも新入社員時代にお世話になりました。
引数にbooleanを取るので、比較式やbooleanを返す判定メソッドを渡して検証するのが一般的。

@Test
public void test02() {
    int sum = add(30, 70);
    assertTrue(sum > 50);
}

エラーメッセージが分かり辛い

というかメッセージらしいメッセージが出ません。
CIでJUnit流すならまず取りたくない選択肢です。

org.junit.Assert.assertThat

JUnit4から導入されました。JUnit4では主流でした。
第一引数に実測値、第二引数にorg.hamcrest.Matcherを渡して検証を行います。
実測値と期待値がassertEqualsと逆なので気を付けましょう。

豊富なMatcherが提供されている為、ほぼ全ての検証はこのassertThatで行えるはず。
Matcherの使い方については下記の記事がとてもわかりやすかったので紹介しておきます。

■HamcrestのMatchersに定義されているメソッドの使い方メモ
https://qiita.com/opengl-8080/items/e57dab6e1fa5940850a3

@Test
public void test04() {
    int sum = add(30, 70);
    assertThat(sum, is(100));
}

@Test
public void test05() {
    String userName = "Yamada Taro";
    assertThat(userName, containsString("Ta"));
}
検証構文の可読性が高い
assert that sum is 100. のように、英文として見た時に読みやすいです。
not()を組み合わせて期待値の真偽を逆にする事も可能です。

Matcherのカスタマイズが可能
Matcherを自作することでプロジェクトに特化した検証が可能です。
エラーメッセージを自分で定義できるのが大きい。

org.assertj.core.api.Assertions.assertThat

個人的には現時点での本命。これからJUnit実装始めるならこれを使いたいです。
JUnitのassertThatとの大きな違いは、引数が実測値のみであり、その後の期待値検証がメソッドチェーンで行えることでしょう。

@Test
public void test01() {
    String userName = "Suzuki Jiro";
    assertThat(userName).contains("Ji");
}

@Test
public void test02() {
    int sum = add(30, 70);
    assertThat(sum).isGreaterThan(50);
}

IDEで検証メソッドの候補が表示される

JunitのassertThatでは第二引数にstaticな検証メソッドを指定しますが、これが意外と辛いです。余程利用頻度が高くない限り、いちいち検証メソッド名など覚えてませんからね。

AssertJのassertThatを利用する場合は、assertThatが返すインスタンスの検証メソッドを呼び出す為、実測値の型に合ったメソッドの候補がIDEに表示されます。
実際使ってみると非常にありがたく感じました。

AssertJの検証メソッドはこちらの記事がよくまとまっていてわかりやすかったので紹介しておきます。

■AssertJ版:テストでよく使う検証メソッド一覧
https://qiita.com/naotawool/items/6512ecbe2fd006dacfd2

com.google.truth.Truth.assertThat

Googleが提供しているアサーションライブラリです。
公式でも謳われていますが、AssertJに非常によく似ており、流れるインタフェースでアサーションが行えます。
ここまで似てるならAssertJでいいかなぁとは思いますが、Truthでは実測値に命名を行うnamedメソッドを提供しており、エラーメッセージに反映することができるようです。
他にも独自の要素がありそうですが未調査・・・
どこかで隙を見てAssertJとの比較をしてみようと思います。

@Test
public void test01() {
    String userName = "Suzuki Jiro";
    assertThat(userName).named("userName").contains("Ji");
}

@Test
public void test02() {
    int sum = add(30, 70);
    assertThat(sum).named("sum").isEqualTo(100);
}

さいごに

というわけで、当分は検証メソッドとしてAssertJのassertThatを使っていこうと思います。
AssertJにはDBテスト用のAssertJ-DBというライブラリもあるようなので、こちらも今後試してみたいですね。