JUnitのアサートの悩み

JUnitのアサートは基本的にisを使えば事足りますが、JavaBeanやListをアサートする場合に悩みます。

JavaBeanのプロパティやListの要素を1つずつアサートするのは面倒ですが、カスタムマッチャーを作るのも面倒だったり・作るほどでもない場合があります。

そうした場合にどうすべきか考えてみました。

isの注意点

org.hamcrest.CoreMatchers.is()は対象クラスのequalsメソッドでアサートを行います。

そのクラスがequalsメソッドをオーバーライドしていない場合、デフォルトのequalsメソッド、つまり、インスタンスの同一性をアサートします。

public class SampleBeanTest {

  @Test
  public void test() {
    SampleBean actual = new SampleBean("test");
    SampleBean expected = new SampleBean("test");
    assertThat(actual, is(expected)); // AssertionError
  }

  public class SampleBean {
    private String str;
    public SampleBean(String str) {
      this.str = str;
    }
    public String getStr() {
      return str;
    }
  }

}

JavaBeanのアサート

org.hamcrest.Matchers.samePropertyValuesAs()を使えばJavaBeanごとアサートできます。

上記のサンプルコードはsamePropertyValuesAsを使えばアサートが成功します。

public class SampleBeanTest {

  @Test
  public void test() {
    SampleBean actual = new SampleBean("test");
    SampleBean expected = new SampleBean("test");
    assertThat(actual, is(samePropertyValuesAs(expected))); // OK
  }

}

ただし、プロパティがJavaBeanの場合はインスタンスの同一性がアサートされるので注意が必要です。

  @Test
  public void test() {
    SampleBean actual = new SampleBean("test", new SampleBean2("test2"));
    SampleBean expected = new SampleBean("test", new SampleBean2("test2"));
    assertThat(actual, is(samePropertyValuesAs(expected))); // AssertionError
  }

  public class SampleBean {
    private String str;
    private SampleBean2 sampleBean2;
    public SampleBean(String str, SampleBean2 sampleBean2) {
      this.str = str;
      this.sampleBean2 = sampleBean2;
    }
    public String getStr() {
      return str;
    }
    public SampleBean2 getSampleBean2() {
      return sampleBean2;
    }
  }

  public class SampleBean2 {
    private String str;
    public SampleBean2(String str) {
      this.str = str;
    }
    public String getStr() {
      return str;
    }
  }

}

参考
JUnit4 で JavaBeans の assertThat を簡潔に書きたい

List(Stringとラッパークラス)のアサート

org.hamcrest.Matchers.contains()を使えば全ての要素を指定してアサートできます。

public class SampleBeanTest {

  @Test
  public void test() {
    List<String> actual = Arrays.asList("test1", "test2", "test3");
    assertThat(actual, contains("test1", "test2", "test3")); // OK
  }

}

ちなみにisでもアサートできました。。

public class SampleBeanTest {

  @Test
  public void test() {
    List<String> actual = Arrays.asList("test1", "test2", "test3");
    List<String> expected = Arrays.asList("test1", "test2", "test3");
    assertThat(actual, is(expected)); // OK
  }

}

参考
JUnit4 で List の assertThat を簡潔に書きたい

List(JavaBean)のアサート

今のところ、よい方法が思いつかないです。

Listを要素ごとにアサートするのは面倒ですし、Listをfor文でアサートするのも良くないです。

ifやforなどのロジックはテストコードの可読性を下げますし、for文はどこでエラーになったのかがわかりづらいです。

ベターな方法は以下ですかね?

  1. リストサイズをアサート
  2. 要素ごとにsamePropertyValuesAsでアサート

それかカスタムマッチャーを作るかです。。

Listのカスタムマッチャー作成方法
JUnit4/カスタムmatcherを作る [Ore Base]

参考
JUnit実践入門 ── 体系的に学ぶユニットテストの技法:書籍案内|技術評論社
第4章 アサーション