JUnit's Built-in Hamcrest Core Matcher Support

1 2 Page 2
Page 2 of 2

Many of the Hamcrest core matchers covered so far increase fluency and readability, but I like the next two for even more reasons. The Hamcrest hasItem() matcher checks for the existence of the prescribed item in the collection and the even more useful Hamcrest hasItems() matcher checks for the existence of multiple prescribed items in the collection. It is easier to see this in code and the following code demonstrates these in action.

Using Hamcrest hasItem() and hasItems()

   @Test
   public void testCreateTreeSetOfStringsHasOneOfAddedStrings()
   {
      final SetFactory factory = SetFactory.newInstance();
      final Set<String> strings = factory.createSet(SetType.TREE, String.class);
      strings.add("Tucson");
      strings.add("Arizona");
      assertThat(strings, hasItem("Tucson"));
   }

   @Test
   public void testCreateTreeSetOfStringsHasAllOfAddedStrings()
   {
      final SetFactory factory = SetFactory.newInstance();
      final Set<String> strings = factory.createSet(SetType.TREE, String.class);
      strings.add("Tucson");
      strings.add("Arizona");
      assertThat(strings, hasItems("Tucson", "Arizona"));
   }

It is sometimes desirable to test the result of a certain tested method to ensure that it meets a wide variety of expectations. This is where the Hamcrest allOf matcher comes in handy. This matcher ensures that all conditions (expressed themselves as matchers) are true. This is illustrated in the following code listing, which tests with a single assert that a generated Set is not null, has two specific Strings in it, and is an instance of TreeSet.

Using Hamcrest allOf()

   @Test
   public void testCreateSetAllKindsOfGoodness()
   {
      final SetFactory factory = SetFactory.newInstance();
      final Set<String> strings = factory.createSet(SetType.TREE, String.class);
      strings.add("Tucson");
      strings.add("Arizona");
      assertThat(
         strings,
         allOf(
            notNullValue(), hasItems("Tucson", "Arizona"), instanceOf(TreeSet.class)));
   }

To demonstrate the Hamcrest core "anyOf" matcher provided out-of-the-box with newer versions of JUnit, I am going to use yet another ridiculously contrived Java class that is in need of a unit test.

Today.java

package dustin.examples;

import java.util.Calendar;
import java.util.Locale;

/**
 * Provide what day of the week today is.
 * 
 * @author Dustin
 */
public class Today
{
   /**
    * Provide the day of the week of today's date.
    * 
    * @return Integer representing today's day of the week, corresponding to
    *    static fields defined in Calendar class.
    */
   public int getTodayDayOfWeek()
   {
      return Calendar.getInstance(Locale.US).get(Calendar.DAY_OF_WEEK);
   }
}

Now I need to test that the sole method in the class above returns a valid integer representing a day of the week correctly. I'd like my test(s) to ensure that a valid integer representing a day Sunday through Saturday is returned, but the method being tested is such that it may not be the same day of the week returned on any given test run. The code listing below indicates how this can be tested with the JUnit-included Hamcrest "anyOf" matcher.

Using Hamcrest anyOf()

   /**
    * Test of getTodayDayOfWeek method, of class Today.
    */
   @Test
   public void testGetTodayDayOfWeek()
   {
      final Today instance = new Today();
      final int todayDayOfWeek = instance.getTodayDayOfWeek();
      assertThat(todayDayOfWeek,
                 describedAs(
                    "Day of week not in range.",
                    anyOf(is(Calendar.SUNDAY),
                          is(Calendar.MONDAY),
                          is(Calendar.TUESDAY),
                          is(Calendar.WEDNESDAY),
                          is(Calendar.THURSDAY),
                          is(Calendar.FRIDAY),
                          is(Calendar.SATURDAY))));
   }

While Hamcrest's allOf requires all conditions to match for the assertion to be avoided, the existence of any one condition is sufficient to ensure that anyOf doesn't lead to an assertion of a failure.

My favorite way of determining which core Hamcrest matchers are available with JUnit is to use import completion in my Java IDE. When I statically import the org.hamcrest.CoreMatchers.* package contents, all of the available matchers are displayed. I can look in the IDE to see what the * represents to see what matchers are available to me.

It is nice to have Hamcrest "core" matchers included with JUnit and this post has attempted to demonstrate the majority of these. Hamcrest offers many useful matchers outside of the "core" that are useful as well. More details on these are available in the Hamcrest Tutorial.

Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)

Related:
1 2 Page 2
Page 2 of 2