November 26, 2014
Hot Topics:

Write More Understandable Java Tests with Matcher Objects and FEST-Assert

  • August 30, 2010
  • By Shekhar Gulati
  • Send Email »
  • More Articles »

The Matchers Provided in the JUnit Library

JUnit comes bundled with a subset of Hamcrest matchers so you don't have to add any new dependency in your application. These matchers can be found in the org.hamcrest.core package of the JUnit JAR. Let’s take a look at some of these matchers:

  1. IsEqual: This matcher tests whether a value is equal to another value. This method uses the equals method for testing equality, for example:
    assertThat("shekhar", equalTo("shekhar"));

    It can also be used to match arrays (including multidimensional), for example:


    String[] s1 = {"a", "b"};
    String[] s2 = {"a", "b"};
    assertThat(s2, equalTo(s1));

    It can also be used with multidimensional arrays as follows:


    int[][] i1 = new int[][]{{1, 2}, {3, 4}};
    int[][] i2 = new int[][]{{1, 2}, {3, 4}};
    assertThat(i2, equalTo(i1));
  2. Is: Is is a matcher that decorates another matcher, retaining the behavior but allowing the test to be more expressive. For example:
    assertThat(name, is(equalTo("shekhar")))
  3. IsNot: This matcher can be used when you need to test for a non-equality, for example:
    assertThat("A",not("B"))
    It can be read as A is not equal to B.
  4. IsNull: This matcher can be used when you need to test for nullability. For example:

    assertThat(null,nullValue());
    assertThat("A",notNullValue());
  5. AllOf: This matcher takes multiple matchers and evaluates to true if all of the passed matchers evaluate to true. AllOf uses shortcut evaluation, so subsequent matchers are not called if an earlier matcher evaluate to false. For example:
    assertThat(list, allOf(notNullValue(),hasSize(1)));
  6. IsInstanceOf : This matcher tests whether a value is an instance of class. For example:

    assertThat(1, instanceOf(Number.class));
    assertThat(null, not(instanceOf(String.class)));

JUnit extended these basic matchers and created some custom matchers, which can be found in the org.junit.matchers package. All the matchers are hosted in a JUnitMatchers class. Let’s look at some of these matchers with a unit test.


import static org.junit.matchers.JUnitMatchers.*;

import java.util.Arrays;
import java.util.List;

import static org.junit.Assert.*;

import static org.hamcrest.CoreMatchers.*;
import org.junit.Before;
import org.junit.Test;

public class JUnitMatchersTest {

private List words;

@Before
public void setUp() {
words = Arrays.asList("available", "avenge", "avenue", "average");
}

/**
* This method tests hasItem matcher which takes an element. This matcher
* matches any collection matching an element.
*/
@Test
public void shouldMatchACollectionContainingAElement() {
assertThat(words, hasItem("available"));
}

/**
* This method tests hasItems matcher which takes multiple elements. This
* matcher matches any collection containing every element in the elements.
*/
@Test
public void shouldMatchCollectionContainingMultipleItems() {
assertThat(words, hasItems("available", "avenge", "avenue"));
}

/**
* This method tests hasItem matcher which takes a matcher. This matcher
* matches any collection containing an element matching elementMatcher
*/
@Test
public void shouldMatchCollectionContainingElementMatcher() {
assertThat(words, hasItem(IsEqual.equalTo("available")));
}

/**
* This method tests hasItems matcher which takes multiple matchers.
*/
@SuppressWarnings("unchecked")
@Test
public void shouldMatchCollectionContainingElementMatchers() {
assertThat(
words,
hasItems(containsString("avail"), containsString("ave"),
containsString("average")));
}

/**
* This method tests everyItem matcher. This matcher matches any collection
* in which every element matches elementMatcher.
*/
@Test
public void shouldHaveEveryItemMatchingElementMatcher() {
assertThat(words, everyItem(containsString("av")));
}
}

Getting the Full Power of Hamcrest

So far we have used only a subset of Hamcrest, which comes bundled with JUnit. To get the full power of Hamcrest we have to use the Hamcrest library. You can download the hamcrest-all-1.3.0RC1.jar from code.google.com. This JAR is not present in any Maven repository so you have to manually install it in your Maven repository.


mvn install:install-file -Dfile=hamcrest-all-1.3.0RC1.jar -DgroupId=org.hamcrest -DartifactId=hamcrest-all -Dversion=1.3.0RC1 -Dpackaging=jar

Here are some of the most important matchers that do are not available in the JUnit library.

  • Beans
    • hasProperty -- Tests JavaBeans properties
  • Collections
    • array -- Tests an array's elements against an array of matchers
    • hasEntry, hasKey, hasValue -- Test a map that contains an entry, key or value
    • hasItemInArray -- Test an array that contains an element
  • Number
    • closeTo -- Tests whether floating point values are close to a given value
    • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo -- Test ordering
  • Text
    • equalToIgnoringCase -- Tests string equality, ignoring case
    • equalToIgnoringWhiteSpace -- Tests string equality, ignoring differences in runs of whitespace
    • containsString, endsWith, startsWith -- Test string matching

Let’s look at some of these matchers more closely:

  1. HasPropertyWithValue : -- This matcher asserts that a JavaBean property on an argument passed to the mock object meets the provided matcher.

    @Test
    public void testHamcrestLibrary() {

    TeamMate actual = new TeamMate("shekhar", "gulati");
    assertThat(actual, hasProperty("firstName",
    IsEqual.equalTo("shekhar")));

    List team = Arrays.asList(new TeamMate("shekhar", "gulati"),new TeamMate("rahul", "sharma"),new TeamMate("sameer", "arora"));
    Matcher withFirstName = hasProperty("firstName", IsEqual.equalTo("shekhar"));
    assertThat(team, hasItem(withFirstName));
    }
  2. IsCollectionWithSize: This matcher checks whether the collection size satisfies a given matcher.
    assertThat(list, hasSize(1));
  3. IsMapContaining: This matcher is for map.

    @Test
    public void testHamcrestMapMethods() {
    Map map = new HashMap();
    map.put("shekhar", "Shekhar Gulati");
    map.put("test", "test123");

    assertThat(map, hasEntry(equalTo("shekhar"), equalTo("Shekhar Gulati")));
    assertThat(map, hasEntry(equalTo("test"), equalTo("test123")));
    assertThat(map, not(hasEntry(equalTo("shekhar"), equalTo("test123"))));
    }
  4. IsIterableContainingInAnyOrder and IsIterableContainingInOrder -- These matchers are used to test whether iterable should be in any order or use natural ordering. You will need to check the use of comparator and compareTo.

    @Test
    public void testIsIterableContainingInAnyOrderAndIsIterableContainingInOrder(){
    List list = Arrays.asList("a","b","c");
    assertThat(list, contains("a","b","c"));
    assertThat(list, contains(equalTo("a"),equalTo("b"),equalTo("c")));
    assertThat(list, containsInAnyOrder("c","a","b"));
    }

    @Test
    public void testHamcrestLibraryIsIterableContainingInOrder() {
    TeamMate shekhar = new TeamMate("shekhar", "gulati");
    TeamMate rahul = new TeamMate("rahul", "sharma");
    TeamMate sameer = new TeamMate("sameer", "arora");
    List team = Arrays.asList(shekhar, rahul, sameer);
    assertThat(team, IsIterableContainingInOrder.contains(new TeamMate(
    "shekhar", "gulati"), new TeamMate("rahul", "sharma"),
    new TeamMate("sameer", "arora")));

    }

While Hamcrest contains lots of built-in matchers, sometimes you will need to write your own matcher to fit your testing needs. (This Hamcrest tutorial explains how to write your own matchers, and you will find a number of Hamcrest extension libraries here.)


Tags: Java, testing



Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel