Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Hamcrest to inspect Map items

Tags:

junit

hamcrest

I have been recently using Hamcrest library to write some tests and quite successful but now I need to do something more complex and started to see a lot of difficulties. I need to inpsect and verify the properties of the items in a Map. My production code looks something like this:

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

I want to write some test codes like the following, but it doesn't compile. Looks like Hamcrest's hasEntry is type-parametered, while hasItem and hasProperty only expect Object.

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

My IDE (Eclipse) is giving this error message: The parameterized method <String, List<HamcrestTest.MyItem>>hasEntry(String, List<HamcrestTest.MyItem>) of type Matchers is not applicable for the arguments (String, Matcher<Iterable<? super Object>>). For one thing I think Eclipse is confused of which hasEntry method I wanted to use, it should be hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher) , not the hasEntry(K key, V value).

Should I just give up and get the item from the Map and manually inspect each property? Is there a cleaner way?

like image 447
dnang Avatar asked Nov 25 '13 16:11

dnang


2 Answers

Youu could just use contains or containsInAnyOrder. True, you'll have to list all items in the List that way, but it works cleaner than 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")))));
}
like image 167
t0mppa Avatar answered Oct 19 '22 21:10

t0mppa


Since @t0mppa didn't provide a good example on how to use Hamcrest's contains and containsInAnyOrder for this, here's a little something to get your started:

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

Note that as opposed to hasItem and hasItems, these will only work if you provide them with a full list of all the values you'll be matching against. See Hamcrest's javadocs for more information.

like image 7
Priidu Neemre Avatar answered Oct 19 '22 21:10

Priidu Neemre