web-dev-qa-db-ja.com

Hamcrestを使用してマップアイテムを検査する方法

私は最近、Hamcrestライブラリを使用していくつかのテストを記述してかなり成功しましたが、今はもっと複雑なことをする必要があり、多くの困難を経験し始めました。マップ内のアイテムのプロパティを調べて確認する必要があります。私の製品コードは次のようになります。

_    Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
    map.put("one", Arrays.asList(new MyItem("One")));
    map.put("two",  Arrays.asList(new MyItem("Two")));
    map.put("three",  Arrays.asList(new MyItem("Three")));
_

次のようなテストコードを記述したいのですが、コンパイルできません。 HamcrestのhasEntryは型パラメーター化されているように見えますが、hasItemとhasPropertyはObjectしか期待していません。

_    assertThat(map, Matchers.<String, List<MyItem>>hasEntry("one",  hasItem(hasProperty("name", is("One")))));
_

私のIDE(Eclipse)がこのエラーメッセージを示しています:タイプMatchersのパラメーター化されたメソッド<String, List<HamcrestTest.MyItem>>hasEntry(String, List<HamcrestTest.MyItem>)は、引数_(String, Matcher<Iterable<? super Object>>)_には適用できません。 1つは、EclipseがどのhasEntryメソッドを使用したいか混乱していると思うのですが、hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher)ではなくhasEntry(K key, V value)にする必要があります。

あきらめてマップからアイテムを取得し、各プロパティを手動で検査する必要がありますか?よりクリーンな方法はありますか?

25
dnang

containsまたはcontainsInAnyOrderを使用できます。確かに、Listのすべての項目をそのようにリストする必要がありますが、hasItemよりもきれいに機能します。

@SuppressWarnings("unchecked")
@Test
public void mapTest() {
  Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
  map.put("one", asList(new MyItem("1"), new MyItem("one")));

  assertThat(map, hasEntry(is("one"),
                           containsInAnyOrder(hasProperty("name", is("one")),
                                              hasProperty("name", is("1")))));
}
34
t0mppa

@ t0mppaはHamcrestのcontainscontainsInAnyOrderを使用する方法の良い例を提供していなかったので、開始するために少し何かを以下に示します。

Map<Integer, String> columns = new HashMap<Integer, String>();
columns.put(1, "ID");
columns.put(2, "Title");
columns.put(3, "Description");

assertThat(columns.values(), contains("ID", "Title", "Description")); // passes
assertThat(columns.values(), contains("ID", "Description", "Title")); // fails
assertThat(columns.values(), containsInAnyOrder("ID", "Description", "Title")); // passes

hasItemおよびhasItemsとは対照的に、これらは、照合するすべての値の完全なリストを提供する場合にのみ機能することに注意してください。詳細については、Hamcrestの javadocs を参照してください。

5
Priidu Neemre

だからこれをもっと簡単にするために、あなたはこれを試すかもしれません...

_assertThat((Object)map, (Matcher)Matchers.hasEntry("one",  hasItem(hasProperty("name", is("One")))));
_

rawタイプに移動すると、警告が表示されますが、コンパイルエラーは発生しません。過去にこのトリックを使用したことがあり、コンパイラーにすべてのキャストを正しく行うことを心配したくない場合。

また、ItIterableContainingInOrder.containingInOrder(new MyItem("One")))の使用を検討することもできます。これによりリスト全体が検証され、MyItemequalsを実装する場合、テストでリフレクションを使用しなくなります。

5
John B