hamcrest の CoreMatchers 詳細

blog1.mammb.com

のついでに hamcrest の CoreMatchers についてまとめます。
Matchers については
blog1.mammb.com

まずは基本の is と not

全体的にはこんな感じ。

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;

public class FooTest {
    @Test public void testFoo() {
        String actual = "foo";
        assertThat(actual, is("foo"));
    }
}

not はこう。

String actual = "foo";
assertThat(actual, not("bar"));
assertThat(actual, is(not("bar")));

equalTo と is

is は equalTo の構文糖であるため、以下は全て等価です。

assertThat(actual, equalTo(expected));
assertThat(actual, is(equalTo(expected)));
assertThat(actual, is(expected));

英語として読み下し易くするために、is に matcher を渡すのが普通です。

インスタンスに関する検証

is(や equalTo)は Object.equals によるオブジェクトの同一性を検証しますが、インスタンスの同一性の検証には sameInstance が用意されています。

List<String> actual = Arrays.asList("foo","bar");
assertThat(actual, is(sameInstance(Arrays.asList("foo","bar"))));  // Assertion Error

List<String> expected = actual;
assertThat(actual, is(sameInstance(expected)));  // OK


instanceOf は型の互換性を検証します。

List<String> actual = Arrays.asList("foo","bar");
assertThat(actual, is(instanceOf((Collection.class))));

null値の検証

null値の検証には nullValue と notNullValue があります

String actual = null;
assertThat(actual, is(nullValue()));

String actual = "hoge";
assertThat(actual, is(notNullValue()));

常にマッチするanything

anything は常にマッチします。テストにてどんな値でも気にしないことを明示する場合に使用できます。

assertThat(actual, is(anything()));
assertThat(actual, is(anything("always matches")));

Assertion Error 時出力を変更する

describedAs を使うと、Assertion Error 時説明をカスタマイズして設定できます。

assertThat("foo", describedAs("foo is not foo1", is("foo")));

この例だと、検証失敗時に「foo is not foo1」の説明を得ることができます。


また、describedAs にはバインド文字列を指定できます。以下のようにすると、

assertThat("foo1", describedAs("foo is not %0", is("foo"), "[foo]"));

Assertion Error の出力は「Expected: foo is not "[foo]"」のように出力されます。

文字列の検証

Hamcrest 1.2 より containsString、startsWith、endsWith といった文字列用の Matcher が追加されました(org.junit.matchers.JUnitMatchers からマージされた)。

String actual = "foobar";
assertThat(actual, is(containsString("ooba")));
assertThat(actual, is(startsWith("foo")));
assertThat(actual, is(endsWith("bar")));

allOf と anyOf

Matcher を AND で検証する allOf

String actual = "foobar";
assertThat(actual, is(allOf(startsWith("fo"), endsWith("ar"))));


Matcher を OR で検証する anyOf

String actual = "foobar";
assertThat(actual, is(anyOf(startsWith("foo"), startsWith("bar"))));

Hamcrest 1.2 で CoreMatchers に追加されたものたち

both と either

String actual = "foobar";
assertThat(actual, both(containsString("a")).or(containsString("c")));
assertThat(actual, both(containsString("a")).and(containsString("b")));
assertThat(actual, both(containsString("a")).and(containsString("c"))); // NG

either も同様です。


コレクション系の everyItem、hasItem、hasItems

Collection<String> actual = Arrays.asList("foo1", "foo2", "foo3");
assertThat(actual, is(everyItem(startsWith("foo"))));
Collection<String> actual = Arrays.asList("foo1", "foo2", "foo3");
assertThat(actual, is(hasItem("foo2")));
Collection<String> actual = Arrays.asList("foo1", "foo2", "foo3");
assertThat(actual, is(hasItems("foo2", "foo3")));

Hamcrest 1.3 で CoreMatchers に追加されたものたち

any と isA が追加されています。いずれも instanceOf のショートカットだと思う・・

assertThat("foo", isA(String.class));
assertThat(10, isA(Number.class));
assertThat("foo", is(any(String.class)));
assertThat(10, is(any(Number.class)));