John is an experienced consultant specialising in Enterprise Java, Web Development, and Open Source technologies, currently based in Sydney, Australia. Well known in the Java community for his many published articles, and as author of Java Power Tools and Jenkins: The Definitive Guide, and founder of the open source Thucydides Automated Acceptance Test Library project, John helps organisations to optimize their Java development processes and infrastructures and provides training and mentoring in agile development, automated testing practices, continuous integration and delivery, and open source technologies in general. John is the CEO of Wakaleo Consulting, and runs several Training Courses on open source Java development tools and best practices. John is a DZone MVB and is not an employee of DZone and has posted 125 posts at DZone. You can read more from them at their website. View Full User Profile

Some useful new Hamcrest matchers for collections

12.16.2011
| 6367 views |
  • submit to reddit

Hamcrest is a neat little library that lets you write more fluent and readable tests. For example, rather than writing:

    assertEquals("red", color);

you would write:

    assertThat(color,is("red"));
This makes for tests that express their intent much more clearly, which in turn makes the tests easier to understand and to maintain, and more likely to be correct. This is generally considered to be a Good Thing.

A version of Hamcrest is actually bundled with JUnit. However it is somewhat dated, and the more recent versions of Hamcrest come with a lot more features, particularly with regards to working with collections. You can use the latest version of Hamcrest by using the junit-dep dependency instead of junit, and configuring your dependencies as shown here:

 <dependency>
	    <groupId>junit</groupId>
	    <artifactId>junit-dep</artifactId>
	    <version>4.10</version>
	    <scope>test</scope>
	    <exclusions>
	        <exclusion>
	            <groupId>org.hamcrest</groupId>
	            <artifactId>hamcrest-core</artifactId>
	        </exclusion>
	    </exclusions>
	</dependency>
	<dependency>
	    <groupId>org.hamcrest</groupId>
	    <artifactId>hamcrest-library</artifactId>
	    <version>1.3.RC2</version>
	</dependency>

You can check the size of a collection directly:

    List colors = Arrays.asList("red","green","blue");
    assertThat(colors, hasSize(3));
You can also check the exact contents of a collection:
 List colors = Arrays.asList("red","green","blue");
    assertThat(colors, contains("red", "green", "blue"));

This last example checks both the contents and the order of the collection. If you are only interested in the contents, you can use containsInAnyOrder:

   List colors = Arrays.asList("red","green","blue");
    assertThat(colors, containsInAnyOrder("green", "red", "blue"));

 

You can also check that a condition is true for every item in a list:

    List ages = Arrays.asList(21, 25,30);
    assertThat(ages, everyItem(greaterThan(18)));

This version is a release candidate, so there might be a few rough edges before the final version. And since the artifact names have changed, you need to be careful to exclude any references to hamcrest-all used by other libraries (lambdaj, for example, uses Hamcrest).

 

From http://weblogs.java.net/blog/johnsmart/archive/2011/12/12/some-useful-new-hamcrest-matchers-collections

Published at DZone with permission of John Ferguson Smart, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Andrew Spencer replied on Fri, 2011/12/16 - 8:20am

JUnit users, be warned that the dependency on Hamcrest is broken up to JUnit 4.9 inclusive.  The dependency on Hamcrest is declared in the POM - but the Hamcrest classes are also included in the junit-dep jar!  So you can never get them off the classpath.  This is corrected in 4.10.

 An alternative to Hamcrest for writing highly readable assertions is fest-assert.  It gives readability on a par with Hamcrest-based asserts, with the extra advantage of using IDE autocomplete.  It also works equally well with TestNG.

Neither of fest-assert nor Hamcrest has an unarguable advantage over the other, but both are clearly better than basic JUnit or TestNG assertions, where it's never explicit which parameter is the expected value and which the observed.  (And to make things worse, TestNG uses the opposite order to JUnit, just to make sure you've no chance of remembering the order.)

Ash Mughal replied on Wed, 2012/01/25 - 7:00pm

Hamcrest is a framework for writing matcher objects allowing 'match' rules to be defined declaratively. There are a number of situations where matchers are invaluble, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use Hamcrest for unit testing.

When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right". Such tests fail when the behaviour of the aspect under test deviates from the expected behaviour, yet continue to pass when minor, unrelated changes to the behaviour are made.

new java

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.