Как использовать Hamcrest для проверки элементов карты

недавно я использовал библиотеку Hamcrest для написания некоторых тестов и довольно успешно, но теперь мне нужно сделать что-то более сложное и начал видеть много трудностей. Мне нужно inpsect и проверить свойства элементов на карте. Мой производственный код выглядит примерно так:

    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")));

Я хочу написать некоторые тестовые коды, как показано ниже, но он не компилируется. Похоже, hasEntry Hamcrest тип-программируемых, а hasItem и метода ожидать только Объект.

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

моя IDE (Eclipse) дает это сообщение об ошибке: параметризованный метод <String, List<HamcrestTest.MyItem>>hasEntry(String, List<HamcrestTest.MyItem>) типа Matchers - это не применимо для Аргументов (String, Matcher<Iterable<? super Object>>). Во-первых, я думаю, что Eclipse путают, из которых hasEntry метод, который я хотел использовать, он должен быть!--6--> , а не hasEntry(K key, V value).

должен ли я просто сдаться и получить элемент с карты и вручную проверить каждое свойство? Есть ли более рациональный способ?

3 ответов


Youu может просто использовать 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")))));
}

поэтому, чтобы сделать это проще, вы можете попробовать это...

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

перейдя к необработанному типу, вы получите предупреждение, но без ошибки компиляции. Если я использовал этот трюк в прошлом, когда я не хочу беспокоиться о том, чтобы получить все кастинг для компилятора.

кроме того, вы можете рассмотреть возможность использования ItIterableContainingInOrder.containingInOrder(new MyItem("One"))). Это проверит весь список, и если MyItem осуществляет equals тогда вы не будете использовать отражение в своих тестах.


С @t0mppa не предоставила хороший пример о том, как использовать Hamcrest-х contains и containsInAnyOrder для этого, вот немного что-то, чтобы начать работу:

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 для получения дополнительной информации.