2009年11月3日火曜日

JUnit4.7 / assertThat() / Matcher

JUnit の assertThat() を調べていたら、カスタム Matcher の書き方を記述している記事が少ないのに気付いたので、以下にサンプルを書いておく。

例えば、テストメソッドの中で以下のように振る舞う Matcher が欲しいとする。(文字の大小を無視した包含の判定)
@Test
public void testContains() {
     assertThat("bc", contains(""));
     assertThat("bc", contains("b"));
     assertThat("bc", contains("B"));
     assertThat("bc", contains("c"));
     assertThat("bc", contains("C"));
     assertThat("bc", contains("bc"));
     assertThat("bc", contains("BC"));

     assertThat("", not(contains("bc")));
     assertThat("bc", not(contains("cd")));
     assertThat("bc", not(contains("Cd")));
     assertThat("bc", not(contains("ab")));
     assertThat("bc", not(contains("aB")));

     assertThat(null, not(contains("ab")));
     assertThat("bc", not(contains(null)));
     assertThat(null, not(contains(null)));
}
その場合、Matcher はこう書く。
package xad.junit47.trial1.util;

import org.hamcrest.Description;
import org.junit.internal.matchers.TypeSafeMatcher;

public class ContainsStringIgnoringCase extends TypeSafeMatcher<String> {
   public static TypeSafeMatcher<String> contains(String criteria) {
      return new ContainsStringIgnoringCase(criteria);
   }

   private final String criteria;

   public ContainsStringIgnoringCase(String criteria) {
      this.criteria = criteria;
   }

   @Override
   public void describeTo(Description description) {
      description.appendText("is contained");
   }

   @Override
   public boolean matchesSafely(String object) {
      return null != object && 
             null != criteria &&
             object.toUpperCase().contains(criteria.toUpperCase());
   }
}
カスタム Matcher は jMock でもかなり使う場面が多いので、いろんな述語を書けるように慣れておくと便利。自動生成させるつもりがなければ、@Factory アノテーションはいらない。

ちなみに、出来合いの Matcher の、is() とか anyOf() とか containsString() とかは、org.hamcrest.CoreMatchers か org.junit.matchers.JUnitMatchers のクラスメソッドなので static import しておけば使える(これも結構わかりづらそう)。

0 件のコメント:

コメントを投稿