JUnit and Hamcrest matchers

By Maurizio Farina | Posted on September 2017

A brief post about the most common JUnit annotations and Hamcrest matchers

Maven dependecies

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.4</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>

Annotations

An example, extracted from ListFeeds.com, on how to use JUnit annotations:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
package com.listfeeds.report;

import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

//Hamrest matchers
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.*;

public class ReportTest {

    // define new log4j report via slf4j logger factory
    private static final Logger log = LoggerFactory.getLogger(ReportTest.class);

    static String tmpFolder = StringUtils.EMPTY;

    ReportHelper helper;

    /**
     * @BeforeClass annotation is used to execute a method only once time before
     *              the class is allocated; so before any of the test methods
     *              execution.
     * 
     * @see http://junit.sourceforge.net/javadoc/org/junit/BeforeClass.html
     */
    @BeforeClass
    public static void runBeforeClass() {

        tmpFolder = System.getProperty("java.io.tmpdir");
        log.debug("runBeforeMethod - setting tmpFolder to[{}]", tmpFolder);

    }

    /**
     * @AfterClass annotation is used to execute a methods only once time after
     *             the class is deallocated so after all test methods execution.
     * 
     * @see http://junit.sourceforge.net/javadoc/org/junit/AfterClass.html
     */
    @AfterClass
    public static void runfterClass() {
        // write here codes to be executed after class is de-istantiated
        log.debug("runfterClass");

    }

    /**
     * @Before annotation is used to execute method before each test method is
     *         executed.
     * 
     */
    @Before
    public void runBeforeMethod() {

        // create new file using temporary folder and UUID
        String reportFile = String.format("%s/testBaseReport_%s.json", tmpFolder, java.util.UUID.randomUUID());
        helper = new ReportHelper(reportFile);

        log.debug("Open new Report before to execute the single test. File [{}]", reportFile);

    }

    /**
     * @After annotation is used to execute method after each test method is
     *        executed.
     * 
     */
    @After
    public void runAfterTestMethod() {

        log.debug("close report after execute the single test");
        helper.close();
    }

    @Test
    public void reportTest() {
        log.debug("reportTest");

        BaseReport report1 = helper.startReport("Report1");
        report1.end();

        assertThat(report1.getLabel(), equalTo("Report1"));
    }

    /**
     * @Test annotation allows to declare which Exception is expected.
     * 
     * The following test attempts to open a file that does not exist. This code throws a FileNotFoundException exception but it's OK because that's what we expected.
     * 
     * @see https://github.com/junit-team/junit4/wiki/Exception-testing
     */
    @Test(expected = FileNotFoundException.class)
    public void testReadFile() throws IOException {
     FileReader reader = new FileReader("fileNotFound.txt");
     reader.read();
     reader.close();

     //JUnit fail statement is used to highlight the test was not successful
     fail("Expected an FileNotFoundException to be thrown");
    }

}

Assertions and Matcher predicates

JUnit supports assertion statements, such as

  • org.junit.Assert.assertArrayEquals, org.junit.Assert.assertEquals
  • org.junit.Assert.assertFalse, org.junit.Assert.assertTrue
  • org.junit.Assert.assertNotNull, org.junit.Assert.assertNull
  • org.junit.Assert.assertNotSame, org.junit.Assert.assertSame

but from JUnit4 is possible to use the more efficient assertion stamentent org.junit.Assert.assertThat with Hamcrest matchers predicates.

The following are the most important Hamcrest matchers:

  • equalTo - test object equality using the equals method
  • allOf - matches if all matchers match (short circuits)
  • anyOf - matches if any matchers match (short circuits)
  • not - matches if the wrapped matcher doesn’t match and vice
  • hasToString - test Object.toString
  • instanceOf, isCompatibleType - test type
  • notNullValue, nullValue - test for null
  • sameInstance - test object identity
  • hasEntry, hasKey, hasValue - test a map contains an entry, key or value
  • hasItem, hasItems - test a collection contains elements
  • hasItemInArray - test an array contains an element
  • closeTo - test floating point values are close to a given value
  • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo
  • equalToIgnoringCase - test string equality ignoring case
  • equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
  • containsString, endsWith, startsWith - test string matching

To use in your code remember to include statement like this

1
import static org.hamcrest.Matchers.equalTo;

The junit-team GitHub page includes a lot of examples.