2013-11-25 4 views
18

Я недавно использовал библиотеку Hamcrest, чтобы написать несколько тестов и довольно успешно, но теперь мне нужно сделать что-то более сложное и начать видеть много трудностей. Мне нужно inpsect и проверить свойства элементов на карте. Мой производственный код выглядит примерно так:Как использовать 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"))); 

Я хочу написать несколько тестовых кодов, как показано ниже, но он не компилируется. Похоже, что hascrnt от Hamcrest имеет параметризацию по типу, а hasItem и hasProperty только ожидают Object.

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 я хотел использовать, он должен быть hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher), а не hasEntry(K key, V value).

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

ответ

21

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"))))); 
} 
+1

Я не считаю, что это будет устранить ошибку времени компиляции, потому что 'hasEntry' возвращает' Сличитель > 'вместо требуемого' Matcher > ' –

+0

@JohnB: Верьте или нет, но я попробовал, и это работает просто персиковый для меня. – t0mppa

+1

Может плохо. Хороший звонок. –

4

Так просто, чтобы сделать это проще, вы могли бы попробовать это ...

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

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

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

1

С @ 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, это будет работать только если вы предоставить им полный список всех значений, которые вы будете соответствующих против. См. javadocs Hamcrest для получения дополнительной информации.

Смежные вопросы