Introduction to Hamcrest Collection Matchers

Another post in the series of Hamcrest Matchers, a framework for writing test matcher objects. This week we’ll dive into collections and iterables, and we’ll see how we can use Hamcrest for making those asserts even more readable. In many software projects I encounter code like the following:

assertEquals("Collection size doesn't match", 4, reds.size());

Or, even worse:

assertTrue(greens.size() == 0);

The second loses context by not knowning the expected value and the actual value; it knows only that they are not equal. So, while this above might be a valid asserts, their readability and error feedback can be improved by using a framework like Hamcrest. This can be done in the following way:

assertThat(reds, hasSize(4));
assertThat(greens, is(empty()));

In my opinion, this increases readability quite a bit, and makes it easier to maintain tests like this. Check the following piece of code for more examples:

    public void testIterablesMatchers() {
        Catalogue catalogue = new Catalogue();

        catalogue.addMovie(new Movie("Lord of the Rings"));
        catalogue.addMovie(new Movie("The Ring"));
        catalogue.addMovie(new Movie("The Bling Ring"));

        List movies = catalogue.getMovies();

        // Check each item for a certain condition
        assertThat(movies, everyItem(Matchers.hasProperty("title", containsString("Ring"))));

        // Checks that the collection has at least one item which matches the specified matcher.
        assertThat(movies, hasItem(new Movie("The Ring")));
        // Checks that the collection has at least one or multiple items which match the specified matcher.
        assertThat(movies, hasItems(new Movie("The Ring"), new Movie("Lord of the Rings")));

        // Creates a matcher matching examined iterables that yield no items.
        assertThat(new ArrayList(), emptyIterable());

        // Checks that all of the items match the expected items, in the same order.
        assertThat(movies, contains(new Movie("Lord of the Rings"), new Movie("The Ring"), new Movie("The Bling Ring")));
        // Checks that all of the items match the expected items, in any order.
        assertThat(movies, containsInAnyOrder(new Movie("The Ring"), new Movie("The Bling Ring"), new Movie("Lord of the Rings")));

        // Beware here: iterableWithSize is a bit funky with Generics, so the bast (and only) way to solve this is to be explicit about the generics
        assertThat(Arrays.asList("foo", "bar"), IsIterableWithSize.iterableWithSize(2));

        // Matches when the size() method returns a value equal to the specified size.
        assertThat(movies, hasSize(3));

        // Checks that the examined collections whose isEmpty method returns true.
        assertThat(new ArrayList(), is(empty()));
        // Checks that the examined collections whose isEmpty method returns true.
        assertThat(new ArrayList(), is(emptyCollectionOf(Movie.class)));
Error messages

Whenever a assertion fails, you get a pretty clear error message, which will help you quickly solve issues you run into. For example, if in the above code example I would have made a wrong assumption, and instead of:

        assertThat(movies, hasSize(3));

If would have typed:

        assertThat(movies, hasSize(2));

The following error message would have shown up:

Expected: a collection with size 
     but: collection size was 

Whereas the the JUnit equivalent:

assertEquals(2, movies.size());

Would have resulted in the following:

Expected :2
Actual   :3

Which would have helped a great deal also, but it’s just that the Hamcrest one is a bit more clear, and a bit more elaborate on the error message. I hope this helps in picking up Hamcrest and that it helps in writing clear, consistent tests. See you next week!

Erik Pragt
Erik Pragt
Erik Pragt is a passionate software developer with a broad range of experience in both static dynamic (Java, Scala) languages. Having worked as a consultant for a broad range of customers mostly in the Telecom, ISP, and banking sector, Erik is now an independent freelance consultant. In the limited time he's not sitting behind the computer he can be found in the gym, riding his motorcycle or diving, always looking for new inspiration.
Recommended Posts
Showing 4 comments

Start typing and press Enter to search