assertEquals()は古い。assertThat()+Matcherを使う。

assertEquals()の方になじみがある方も多いかも知れないが、assertThat()を使う方が便利。そろそろassertEquals()は卒業したい。

JUnitが出始めのころに使い方を覚えた人は、assertEquals()やassertTrue()などの方がなじみがある。しかし最近はassertThat()を使う方が普通で便利。assertThat()はJUnit4.4(2007年リリース)から追加された。JUnit4.4のリリースから5年以上経ち情報も増えてきた。そろそろassertEquals()は卒業したい。

assertEquals()の限界

assertEquals()では「equals()」あるいは「==」を利用した検証になる。

assertEquals()を用いたテスト
String expected = "Hello World";
String actual = "Hello" + " " + "World";
assertEquals(expected, actual);

基本的には問題ない。これでもやっていける。ただこの「equals()」に頼っていることが問題になる。

オブジェクトにequals()は一つしか作れない。equals()に定義してある内容(状況)と違う検証をしようとするときに困ってしまう。これを回避しようとするとフィールドの数分assertEquals()を書いたりする事態になったりするのでうれしくない。そもそも「equals()」を必ずしも定義するとも限らない。

というわけで、なんとなくassertEquals()を使ってきたかもしれないが不便なところ(改善点)も存在する。

検証処理をMatcherとして分離する

assertEquals()の限界に対処するassertThat()とMatcherの仕組みがJUnit4.4から登場する。

Matcherクラス図
Figure 1. Matcherクラス
assertThat()とMatcherを用いたテスト
String expected = "Hello World";
String actual = "Hello" + " " + "World";
assertThat(actual, is(expected));

一見するとあまり変わったように見えない。actualとexpectedが逆になったぐらい。

重要なのはassertThat自体は検証処理をしていなくて、Matcherオブジェクト検証処理を行っていること。(is()というのはCoreMachersクラスのメソッドでMacherのファクトリ)

このように検証処理をMatcherに分離することで、Matcherを作ってしまえばオブジェクトのequals()の内容にかかわらず検証することができるという仕組み。これによりequals()の問題を回避できる。(もちろんeauals()を用いた検証するMatcherもある)

そして、検証メソッドはassertThatに固定されるのでassertEqualsを何個も何個もという事態ももちろんなくなる。この他にも、次のようなメリットがある。

  • 自然な可読

  • 詳細なエラーメッセージ

このようにassertThatとMatcherの方が、assertEquals()より手広くなりメリットも多いので切り替えるべき。

まずはCoreMatchersを使えるようにする

検証処理がMatcherオブジェクトに任されるようになったので、毎回Matcherを作るのかといえばそんなことにはならない。汎用的なものはCoreMatchersやMatchersクラスのファクトリで提供される。少し特別な検証をしたいときだけ自作する。

CoreMatchersクラス図
Figure 2. CoreMatchersクラス

Matcher API はもともとHamcrestというライブラリのものだった。 メジャーなものはバージョン4.4から本家に組み込まれたのでJUnitが利用できるなら設定なしで仕様できる。

assertThatとMatcherの入りとしてはCoreMatchersに慣れること。is(),not(),nullValue(),sameInstance()あたりが使えればよい。難しいことはないのでスタイルに慣れることが重要。

特にis()がわかればassertEquals()と同等のことは可能なのでスタートはそこから。

Appendix B: 改訂履歴

  • v1.0, 2017-04-12: 初稿