JUnit4.4のassertThatを使ってみた

せっかくのassertThatもMactherのバリエーション不足で威力を発揮しきれないって感じ.まあ,今後に期待ってところか.


あと,AssertとかMatcherはstaticインポートしてナンボなワケで,オンデマンドでimport static文を生成してもうれしくも何ともないので,ハナっから

import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.*;

って宣言してないと使いづらいこと,この上なかった(さらに「*」は必須).


まず,org.junit.matchersJUnitMacthersを使った場合.

package com.example;

import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.*;

import java.util.Arrays;
import java.util.List;

public class JUnitTest {
    @Test public void 文字列のテスト() {
        String str = "The quick brown fox jumps over the lazy dog.";
        assertThat(str, containsString("fox"));
        assertThat(str, either(containsString("fox"))
                            .or(containsString("FOX")));
        assertThat(str, either(containsString("fox"))
                            .and(containsString("dog")));
        assertThat(str, both(containsString("fox"))
                            .and(containsString("dog")));
    }

    @Test public void コレクションのテスト() {
        List<Integer> list = Arrays.asList(1, 2, 5, 10, 15);
        assertThat(list, hasItem(1));
        assertThat(list, hasItems(1, 10, 15));

        List<String> list2 = Arrays.asList("aaa", "bbcc", "ccc");
        assertThat(list2, each(either(containsString("aaa"))
                                        .or(containsString("cc"))));
    }
}

事実上,具体的なMatcherはcontainsString()しか無い(一応,hasItem()/hasItems()もそうか).eitherとbothは,実体は同じCombinableMatcherだから,文芸的な意味付けをしたい場合に使い分けるんだろうな(orで繋げる場合はeither,andで繋げる場合はbothとかって).


なんにしろ,これだけじゃ使えんよ.:-(


で,JUnit4.4にバンドルされたhamcrest(core)のCoreMatchersを使った場合.

package com.example;

import org.junit.Test;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

import java.util.ArrayList;
import java.util.List;

public class HamcrestTest {
    @Test public void CoreMatchersの確認() {
        assertThat(1, is(1));
        assertThat(1, equalTo(1));
        assertThat(1, is(equalTo(1)));

        assertThat(1, not(2));
        assertThat(1, is(not(2)));

        assertThat("str", is("str"));

        assertThat("str", is(String.class));
        assertThat("str", instanceOf(String.class));
        assertThat("str", is(instanceOf(String.class)));

        String str1 = "some";
        String str2 = new String(str1);
        assertThat(str1, is(str2));
        assertThat(str1, sameInstance(str1));
        assertThat(str1, not(sameInstance(str2)));

        assertThat(new ArrayList(), is(List.class));

        assertThat("hoge", notNullValue());
        assertThat("hoge", notNullValue(String.class));
        assertThat("hoge", is(notNullValue()));
        assertThat("hoge", is(not(nullValue())));

        assertThat(null, nullValue());
        assertThat(null, is(nullValue(String.class)));

        assertThat("str", allOf(is("str"), is(String.class)));
        assertThat("str", anyOf(is("str"), is(Number.class)));
        assertThat(null, anything("とりあえず何でも良い"));
        assertThat(null, any(String.class));
    }
}

is()がやたらと万能なんで,わざわざequalTo()とinstanceOf()を使う必要がない.あとJUnitMatchersのeither()/both()より,allOf()/anyOf()のほうが使い勝手が良い.


んが,それでもまだ物足りない.なんだかんだで実用レベルのMatcherを用意しようと思ったら,hamcrest-library.jarを加えて,

import static org.hamcrest.Matchers.*;

を使わないと話にならんかもダ.
hamcrest-libraryのMatchersについては,The Hamcrest Tutorialの"A tour of common matchers"を参照してちょ.