HamcrestのMatchersに定義されているメソッドの使い方メモ

  • 221
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Hamcrest の Matcher にどんなものがあるかメモ。

標準でどんな Matcher があるか知っておかないと、ついつい車輪の再発明をしてしまう(というか、してしまった)。

なので、とりあえず org.hamcrest.Matchers に定義されているメソッドをひと通り確認した。

ただし、使い方がよくわからないやつ(iterableWithSize())、他のメソッドで事足りるやつ(both(), either(), any())、個人的に使わなさそうなやつ(hasXPath())は省いている。

環境

バージョン

JUnit

4.11

Hamcrest

1.3

build.gradle

build.gradle
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.11', {
        transitive = false
    }
    testCompile 'org.hamcrest:hamcrest-all:1.3'
}
>gradle dependencies

testCompile - Compile classpath for source set 'test'.
+--- junit:junit:4.11
\--- org.hamcrest:hamcrest-all:1.3

JUnit 4.11 はデフォルトだと hamcrest-core の 1.3 に依存している。

今回は別途 hamcrest-all を依存関係に追加するので、 transitive = false を指定して、推移的な依存関係の解決を明示的に解除している。

基本的な比較 Matcher

is() : 同じ値であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("hoge", is("hoge"));
    }
}
  • 指定した値が等しいことをチェックする。
  • 比較には、 equals(Object) メソッドが使用される。

not() : 否定する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void 値を否定する() {
        assertThat("hoge", is(not("HOGE")));
    }

    @Test
    public void Matcherを否定する() {
        assertThat("hoge", is(not(containsString("xx"))));
    }
}
  • 引数で指定した値(Matcher)を否定する。

nullValue() : null であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat(null, is(nullValue()));
    }
}
  • 値が null であることをチェックする。

notNullValue() : null でないことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat("not null", is(notNullValue()));
    }
}
  • 値が null でないことをチェックする。

equalTo() : 同じ値であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("hoge", is(equalTo("hoge")));
    }

    @Test
    public void テストは失敗する() {
        assertThat("hoge", is(equalTo("xxx")));
    }
}
  • 動作は is() と同じ。
  • 英語の文法的に is() だと不自然なときは equalTo() を使う感じかと。

comparesEqualTo() : compareTo() で比較する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    private Hoge one = new Hoge();
    private Hoge other = new Hoge();

    @Test
    public void テストは成功する() {
        assertThat(one, is(comparesEqualTo(other)));
    }

    @Test
    public void テストは失敗する() {
        assertThat(one, is(other));
    }

    public static class Hoge implements Comparable<Hoge> {
        @Override
        public int compareTo(Hoge o) {
            return 0;
        }

        @Override
        public boolean equals(Object other) {
            return false;
        }

        @Override
        public int hashCode() {
            return super.hashCode();
        }
    }
}
  • equals() メソッドではなく、 compareTo() メソッドで比較し、 0 が返される場合にチェックが OK となる。

sameInstance() : 同じインスタンスであることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        Hoge hoge = new Hoge();
        assertThat(hoge, is(sameInstance(hoge)));
    }

    private static class Hoge {}
}
  • インスタンスが同じであることをチェックする。

instanceOf() : 指定したクラスのインスタンスであることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    private Hoge hoge = new Hoge();
    private Fuga fuga = new Fuga();

    @Test
    public void テストは成功する() {
        assertThat(hoge, is(instanceOf(Hoge.class)));
        assertThat(fuga, is(instanceOf(Hoge.class)));
    }

    @Test
    public void テストは失敗する() {
        assertThat(hoge, is(instanceOf(String.class)));
    }

    private static class Hoge {}
    private static class Fuga extends Hoge {}
}
  • インスタンスが、指定したクラス、またはそのサブクラスのインスタンスであることをチェックする。

hasToString() : toString() で比較する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static Hoge hoge = new Hoge();

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(hoge, hasToString("hoge"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(hoge, hasToString("xxxx"));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(hoge, hasToString(containsString("og")));
        }

        @Test
        public void テストは失敗する() {
            assertThat(hoge, hasToString(containsString("xx")));
        }
    }

    private static class Hoge {
        @Override
        public String toString() {
            return "hoge";
        }
    }
}
  • toString() した結果をチェックする。

文字列比較に関係する Matcher

startsWith() : 指定した文字で始まることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat("hoge", is(startsWith("h")));
    }

    @Test
    public void テストは失敗する() {
        assertThat("hoge", is(startsWith("x")));
    }
}
  • 指定した文字列で始まることをチェックする。

endsWith() : 指定した文字で終わることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("hoge", is(endsWith("e")));
    }

    @Test
    public void テストは失敗する() {
        assertThat("hoge", is(endsWith("xxx")));
    }
}
  • 指定した文字列で終わることをチェックする。

containsString() : 指定した文字が含まれることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("hoge", is(containsString("og")));
    }

    @Test
    public void テストは失敗する() {
        assertThat("HOGE", is(containsString("og")));
    }
}
  • 指定した文字列が含まれることをチェックする。

equalToIgnoringCase() : 大文字・小文字を区別せずに比較する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("hoge", is(equalToIgnoringCase("HOGE")));
    }
}
  • 大文字・小文字を区別せずに文字列を比較する。

equalToIgnoringWhiteSpace() : 大文字・小文字・ブランク文字を無視して比較する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("h o g\te", is(equalToIgnoringWhiteSpace("   H\tO        G E   ")));
    }
}
  • 次のことを無視して比較する。
    • 大文字・小文字。
    • ブランク文字(半角・全角スペース、タブ)の違い。
    • 文字列の間にあるブランク文字の数。
    • 前後のブランク文字。

isEmptyString() : 空文字であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("", isEmptyString());
    }
}
  • 文字列が空文字であることをチェックする。

isEmptyOrNullString() : 空文字または null であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat("", isEmptyOrNullString());
        assertThat(null, isEmptyOrNullString());
    }
}
  • 文字列が空文字または null であることをチェックする。

stringContainsInOrder() : 指定した順序で文字列が現れることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.Arrays;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat("HogeFugaPiyo", is(stringContainsInOrder(Arrays.asList("Hog", "eFug", "aPiyo"))));
    }

    @Test
    public void テストは失敗する() {
        assertThat("HogeFugaPiyo", is(stringContainsInOrder(Arrays.asList("Fuga", "Piyo", "Hoge"))));
    }
}
  • 指定した文字列が、指定した順序で現れることをチェックする。

数値比較に関係する Matcher

closeTo() : 指定した範囲の値であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat(0.5, is(closeTo(1.0, 0.5)));
    }


    @Test
    public void テストは失敗する() {
        assertThat(0.4, is(closeTo(1.0, 0.5)));
    }
}
  • 第一引数で指定した値を基準として、第二引数で指定した値の範囲に数値が収まることをチェックする。
  • 上記例の場合、値が 0.5 ~ 1.5 ならテストが成功する。
  • BigDecimal 版もある。

greaterThan() : 指定した値より大きいことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat(10, is(greaterThan(9)));
    }

    @Test
    public void テストは失敗する() {
        assertThat(10, is(greaterThan(10)));
    }
}
  • 指定した値より大きいことをチェックする。

greaterThanOrEqualTo() : 指定した値以上であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テストは成功する() {
        assertThat(10, is(greaterThanOrEqualTo(10)));
    }

    @Test
    public void テストは失敗する() {
        assertThat(10, is(greaterThanOrEqualTo(11)));
    }
}
  • 指定した値以上であることをチェックする。

lessThan() : 指定した値より小さいことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat(10, is(lessThan(11)));
    }

    @Test
    public void テストは失敗する() {
        assertThat(10, is(lessThan(10)));
    }
}
  • 指定した値より小さいことをチェックする。

lessThanOrEqualTo() : 指定した値以下であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat(10, is(lessThanOrEqualTo(10)));
    }

    @Test
    public void テストは失敗する() {
        assertThat(10, is(lessThanOrEqualTo(9)));
    }
}
  • 指定した値以下であることをチェックする。

正直、この辺は普通に比較演算子使った方が読みやすい気がする。。。

Collection・Iterableに関係する Matcher

contains() : 全ての要素が等しいことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

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

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static List<String> list = Arrays.asList("hoge", "fuga", "piyo");

    public static class 値を渡す {
        @Test
        public void テストは成功する() {
            assertThat(list, is(contains("hoge", "fuga", "piyo")));
        }

        @Test
        public void 要素数が異なるので_テストは失敗する() {
            assertThat(list, is(contains("hoge", "fuga")));
        }

        @Test
        public void 含まれる要素が異なるので_テストは失敗する() {
            assertThat(list, is(contains("hoge", "fuga", "PIYO")));
        }

        @Test
        public void 順序が異なるので_テストは失敗する() {
            assertThat(list, is(contains("hoge", "piyo", "fuga")));
        }
    }

    public static class Matcherを渡す {
        @Test
        public void テストは成功する() {
            assertThat(list, is(contains(equalTo("hoge"), containsString("ug"), startsWith("pi"))));
        }

        @Test
        public void 要素数が異なるので_テストは失敗する() {
            assertThat(list, is(contains(equalTo("hoge"), containsString("ug"))));
        }

        @Test
        public void 条件を満たさないMatcherが含まれるので_テストは失敗する() {
            assertThat(list, is(contains(equalTo("HOGE"), containsString("ug"), startsWith("pi"))));
        }

        @Test
        public void 順序が異なるので_テストは失敗する() {
            assertThat(list, is(contains(containsString("ug"), equalTo("hoge"), startsWith("pi"))));
        }
    }

}
  • Iterable インターフェースを実装したクラス(List とか)の要素が、指定した内容で完全に一致することをチェックする。

containsInAnyOrder() : 順序を無視して全ての要素が含まれることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

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

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static List<String> list = Arrays.asList("hoge", "fuga", "piyo");

    public static class 値を渡す {
        @Test
        public void テストは成功する() {
            assertThat(list, is(containsInAnyOrder("hoge", "piyo", "fuga")));
        }

        @Test
        public void 要素数が異なるので_テストは失敗する() {
            assertThat(list, is(containsInAnyOrder("hoge", "fuga")));
        }

        @Test
        public void 含まれる要素が異なるので_テストは失敗する() {
            assertThat(list, is(containsInAnyOrder("hoge", "PIYO", "fuga")));
        }
    }

    public static class Matcherを渡す {
        @Test
        public void テストは成功する() {
            assertThat(list, is(containsInAnyOrder(containsString("ug"), startsWith("pi"), equalTo("hoge"))));
        }

        @Test
        public void 要素数が異なるので_テストは失敗する() {
            assertThat(list, is(containsInAnyOrder(containsString("ug"), equalTo("hoge"))));
        }

        @Test
        public void 条件を満たさないMatcherが含まれるので_テストは失敗する() {
            assertThat(list, is(containsInAnyOrder(containsString("ug"), equalTo("HOGE"), startsWith("pi"))));
        }
    }

}
  • 要素の順番は無視して、 Iterable インターフェースを実装したクラス(List とか)の要素に、指定した要素が全て含まれることをチェックする。

hasItem() : 指定した要素を持つことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

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

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static List<String> list = Arrays.asList("hoge", "fuga", "piyo");

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasItem("hoge"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(list, hasItem("xxx"));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasItem(containsString("og")));
        }

        @Test
        public void テストは失敗する() {
            assertThat(list, hasItem(containsString("xxx")));
        }
    }
}
  • Iterable を実装したクラスの要素に、指定した値が含まれることをチェックする。

hasItems() : 指定した要素を全て含むことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

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

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static List<String> list = Arrays.asList("hoge", "fuga", "piyo");

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasItems("hoge", "piyo"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(list, hasItems("xxx"));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasItems(containsString("og"), endsWith("ga")));
        }

        @Test
        public void テストは失敗する() {
            assertThat(list, hasItems(containsString("xxx")));
        }
    }
}
  • hasItem() の、要素を複数指定できる版。

hasSize() : 指定したサイズであることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

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

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static List<String> list = Arrays.asList("hoge", "fuga", "piyo");

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasSize(3));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasSize(lessThan(4)));
        }
    }
}
  • 指定したコレクションのサイズをチェックする。

empty() : 空であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.Collections;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat(Collections.emptyList(), is(empty()));
    }
}
  • 指定したコレクションが空であることをチェックする。

emptyCollectionOf() : 指定したクラスの空コレクションであることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.Collections;
import java.util.List;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        List<String> list = Collections.emptyList();
        assertThat(list, is(emptyCollectionOf(String.class)));
    }
}
  • コレクションが、指定したクラスの空のコレクションであることをチェックする。

emptyIterable() : 空の Iterator であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.Collections;
import java.util.Iterator;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        MyIterable iterable = new MyIterable();
        assertThat(iterable, is(emptyIterable()));
    }

    public static class MyIterable implements Iterable<MyIterable> {
        @Override
        public Iterator<MyIterable> iterator() {
            return Collections.emptyIterator();
        }
    }
}
  • Iterable を実装したクラスが空であることをチェックする。

emptyIterableOf() : 指定したクラスの空の Iterator であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.Collections;
import java.util.Iterator;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        MyIterable iterable = new MyIterable();
        assertThat(iterable, is(emptyIterableOf(MyIterable.class)));
    }

    public static class MyIterable implements Iterable<MyIterable> {
        @Override
        public Iterator<MyIterable> iterator() {
            return Collections.emptyIterator();
        }
    }
}
  • Iterable を実装したクラスが、指定したクラスの空の Iterator であることをチェックする。

Map に関係する Matcher

hasEntry() : 指定したエントリを持つことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static Map<String, String> map = new HashMap<>();

    static {
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
    }

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(map, hasEntry("hoge", "HOGE"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(map, hasEntry("xxxx", "HOGE"));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(map, hasEntry(containsString("og"), endsWith("E")));
        }

        @Test
        public void テストは失敗する() {
            assertThat(map, hasEntry(containsString("xx"), endsWith("E")));
        }
    }
}
  • 指定したエントリがマップに含まれることをチェックする。

hasKey() : 指定したキーを持つことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static Map<String, String> map = new HashMap<>();

    static {
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
    }

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(map, hasKey("hoge"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(map, hasKey("xxxx"));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(map, hasKey(containsString("og")));
        }

        @Test
        public void テストは失敗する() {
            assertThat(map, hasKey(containsString("xx")));
        }
    }
}
  • 指定したキーをマップが持つことをチェックする。

hasValue() : 指定した値を持つことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static Map<String, String> map = new HashMap<>();

    static {
        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");
    }

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(map, hasValue("HOGE"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(map, hasValue("xxxx"));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(map, hasValue(endsWith("E")));
        }

        @Test
        public void テストは失敗する() {
            assertThat(map, hasValue(endsWith("xxx")));
        }
    }
}

JavaBeans に関係する Matcher

hasProperty() : 指定したプロパティを持つことをチェックする

Hoge.java
package sample.hamcrest;

public class Hoge {
    private int value;

    public Hoge(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}
package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static Hoge hoge = new Hoge(10);

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(hoge, hasProperty("value"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(hoge, hasProperty("xxx"));
        }
    }

    public static class Matcherを使って値もチェックする {
        @Test
        public void テストは成功する() {
            assertThat(hoge, hasProperty("value", greaterThan(9)));
        }

        @Test
        public void テストは失敗する() {
            assertThat(hoge, hasProperty("value", equalTo(11)));
        }
    }
}
  • 指定した名前の JavaBeans プロパティを持つことをチェックする。
  • Matcher を渡すことで、値もチェックすることができる。

  • 指定した値が、マップのバリューに存在することをチェックする。

samePropertyValuesAs() : 全てのプロパティが等しいことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        Hoge one = new Hoge(10, "one");
        Hoge other = new Hoge(10, "one");

        assertThat(one, is(samePropertyValuesAs(other)));
    }

    @Test
    public void テストは失敗する() {
        Hoge one = new Hoge(10, "one");
        Hoge other = new Hoge(99, "other");

        assertThat(one, is(samePropertyValuesAs(other)));
    }

    public static class Hoge {
        private int i;
        private String value;

        public Hoge(int i, String value) {
            this.i = i;
            this.value = value;
        }

        public int getI() {
            return this.i;
        }
        public void setI(int i) {
            this.i = i;
        }
        public String getValue() {
            return this.value;
        }
        public void setValue(String value) {
            this.value = value;
        }
    }
}
  • JavaBeans プロパティを比較する。

Matcher を組み合わせる

allOf() : Matcher を AND 条件で結合する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat("hoge", is(allOf(startsWith("h"), containsString("og"), endsWith("e"))));
    }

    @Test
    public void テストは失敗する() {
        assertThat("hoge", is(allOf(startsWith("h"), containsString("xx"), endsWith("e"))));
    }
}
  • 引数で渡した Matcher が全て満たされることをチェックする。

anyOf() : Matcher を OR 条件で結合する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat("hoge", is(anyOf(startsWith("h"), endsWith("xxx"))));
    }

    @Test
    public void テストは失敗する() {
        assertThat("yyyy", is(anyOf(startsWith("h"), endsWith("xxx"))));
    }
}
  • 引数で渡した Matcher の内、最低でも1つは条件を満たすことをチェックする。

配列に関係する Matcher

array() : 配列の各要素を Matcher で検証する

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        String[] array = {"hoge", "fuga", "piyo"};
        assertThat(array, is(array(equalTo("hoge"), startsWith("f"), endsWith("o"))));
    }

    @Test
    public void 要素数に対してMatcherの数が異なるので_テストは失敗する() {
        String[] array = {"hoge", "fuga", "piyo"};
        assertThat(array, is(array(equalTo("hoge"), startsWith("f"))));
    }

    @Test
    public void 条件を満たさないMatcherがあるので_テストは失敗する() {
        String[] array = {"hoge", "fuga", "piyo"};
        assertThat(array, is(array(equalTo("hoge"), startsWith("f"), equalTo("PIYO"))));
    }
}
  • 配列1つずつに対して Matcher を適用し、全ての Matcher が条件を満たすことをチェックする。

arrayContaining() : 指定した要素と配列の要素が全て等しいことをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    public static class 値を渡す {
        @Test
        public void テストは成功する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContaining("hoge", "fuga", "piyo")));
        }

        @Test
        public void 要素数が異なるので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContaining("hoge", "fuga")));
        }

        @Test
        public void 条件を満たさないMatcherがあるので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContaining("HOGE", "fuga", "piyo")));
        }
    }

    public static class Matcherを渡す {
        @Test
        public void テストは成功する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContaining(equalTo("hoge"), containsString("ug"), endsWith("o"))));
        }

        @Test
        public void 要素数が異なるので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContaining(equalTo("hoge"), containsString("ug"))));
        }

        @Test
        public void 条件を満たさないMatcherがあるので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContaining(equalTo("hoge"), containsString("ug"), endsWith("xxx"))));
        }
    }
}
  • 配列の中身が、引数で渡した値(Matcher)と完全に一致することをチェックする。

arrayContainingInAnyOrder() : 順序を無視して、指定した要素が全て配列に含まれることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    public static class 値を渡す {
        @Test
        public void テストは成功する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContainingInAnyOrder("hoge", "piyo", "fuga")));
        }

        @Test
        public void 指定した要素が全て含まれていないので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContainingInAnyOrder("hoge", "piyo")));
        }
    }

    public static class Matcherを渡す {
        @Test
        public void テストは成功する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContainingInAnyOrder(equalTo("piyo"), equalTo("hoge"), endsWith("a"))));
        }

        @Test
        public void fugaにマッチするMatcherが存在しないので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayContainingInAnyOrder(equalTo("piyo"), equalTo("hoge"), endsWith("yo"))));
        }
    }
}
  • 要素の順番は無視して、配列の要素に指定した値が全て含まれることをチェックする。

arrayWithSize() : 配列のサイズをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    public static class 値を渡す {
        @Test
        public void テストは成功する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayWithSize(3)));
        }

        @Test
        public void サイズが異るので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayWithSize(2)));
        }
    }

    public static class Matcherを渡す {
        @Test
        public void テストは成功する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayWithSize(lessThan(4))));
        }

        @Test
        public void 条件を満たさないので_テストは失敗する() {
            String[] array = {"hoge", "fuga", "piyo"};
            assertThat(array, is(arrayWithSize(greaterThan(3))));
        }
    }
}
  • 配列のサイズが指定した値と同じであること(Matcher の条件を満たすこと)をチェックする。

emptyArray() : 配列が空であることをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat(new String[] {}, is(emptyArray()));
    }
}
  • 指定した配列が空であることをチェックする。

hasItemInArray() : 配列の中に指定した値が存在することをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

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

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    private static String[] list = {"hoge", "fuga", "piyo"};

    public static class 値を指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasItemInArray("hoge"));
        }

        @Test
        public void テストは失敗する() {
            assertThat(list, hasItemInArray("xxx"));
        }
    }

    public static class Matcherを指定する {
        @Test
        public void テストは成功する() {
            assertThat(list, hasItemInArray(containsString("og")));
        }

        @Test
        public void テストは失敗する() {
            assertThat(list, hasItemInArray(containsString("xxx")));
        }
    }
}
  • 配列の要素に、指定した値が含まれることをチェックする。

その他

describedAs() : テストに失敗したときのメッセージを上書きする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {
    @Test
    public void テスト1() {
        assertThat("hoge", is(equalTo("HOGE")));
    }

    @Test
    public void テスト2() {
        assertThat("hoge", is(describedAs("HOGE [%0, %1]", equalTo("HOGE"), "param1", "param2")));
    }
}
テスト1の実行結果
java.lang.AssertionError: 
Expected: is "HOGE"
     but: was "hoge"
テスト2の実行結果
java.lang.AssertionError: 
Expected: is HOGE ["param1", "param2"]
     but: was "hoge"
  • テストが失敗したときの説明メッセージを、指定したものに置き換える。
  • %0 という形で埋め込みパラメータが使える。

isIn() : 配列かコレクションで指定した要素のいずれかに一致することをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.Arrays;

import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class HamcrestTest {

    public static class コレクションを指定する {
        @Test
        public void テストは成功する() {
            assertThat("hoge", isIn(Arrays.asList("hoge", "fuga", "piyo")));
        }

        @Test
        public void テストは失敗する() {
            assertThat("xxxx", isIn(Arrays.asList("hoge", "fuga", "piyo")));
        }
    }

    public static class 配列を指定する {
        @Test
        public void テストは成功する() {
            assertThat("hoge", isIn(new String[] {"hoge", "fuga", "piyo"}));
        }

        @Test
        public void テストは失敗する() {
            assertThat("xxxx", isIn(new String[] {"hoge", "fuga", "piyo"}));
        }
    }
}
  • 指定したコレクション(配列)の中に、 assertThat() の第一引数で指定した要素が存在することをチェックする。

isOneOf() : 可変長引数で指定した値のいずれかに一致することをチェックする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat("hoge", isOneOf("hoge", "fuga", "piyo"));
    }

    @Test
    public void テストは失敗する() {
        assertThat("xxxx", isOneOf("hoge", "fuga", "piyo"));
    }
}
  • 可変長引数で指定した値の中に、 assertThat() の第一引数で指定した要素が存在することをチェックする。

anything() : 全ての値にマッチする

package sample.hamcrest;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import java.util.Arrays;

import org.junit.Test;

public class HamcrestTest {

    @Test
    public void テストは成功する() {
        assertThat("hoge", is(anything()));
        assertThat("fuga", is(anything()));
        assertThat(123,    is(anything()));
        assertThat(Arrays.asList("a", "b", "c"), is(anything()));
    }
}
  • 全ての値にマッチする。