Newer
Older
labs / tiddlers / content / reference / Testing / _Reference_Testing_Hamcrest.md

There are two different libraries available to you for writing assertions in your tests:

  • JUnit --- these usually start with assertTrue and assertEquals.

    These assertions are fairly simplistic and you often need to write more code to use them.

  • Hamcrest --- these usually start with assertThat.

    These assertions are more powerful and resemble English which makes the intention of an assertion more obvious. The messages that are produced when a Hamcrest assertion fails are often easier to understand than the generic true/equals tests that you get with JUnit.

We will generally stick to Hamcrest in {{$:/ou/parameters/Paper Code}} since it is the more powerful library, and is generally easier to use.

Testing Domain Objects with Hamcrest

Student student = studentDao.searchById(12345);

// ensure the method returned doris
assertThat(student, is(doris));

// ensure that the returned object has identical field values as original object
assertThat(student, samePropertyValuesAs(doris));

// ensure that returned object has specific field values
assertThat(student, hasProperty("name", equalTo("Doris")));
assertThat(student, hasProperty("major", equalTo("Information Science")));

// ensure that returned object is null
assertThat(student, is(nullValue()));

// ensure that returned object is NOT null
assertThat(student, is(notNullValue()));

Testing Collections with Hamcrest

Collection<Student> students = studentDao.getStudents();

// ensure that doris exists in the collection
assertThat(students, hasItem(doris));

// ensure that doris and horace exist in the collection
assertThat(students, hasItems(doris, horace));

// ensure that boris does NOT exist in the collection
assertThat(students, not(hasItem(boris)));

// check that the collection has a specific size
assertThat(students, hasSize(3));

// check all elements exist in a particular order (must list all elements of the collection)
assertThat(students, contains(doris, horace, morris));

// check all elements exist in any order (must list all elements of the collection)
assertThat(students, containsInAnyOrder(doris, horace, morris));

Floating-point Numbers

If you are using doubles or floats then you have to account for the approximation error in your tests. You can do this as follows:

Double total = sale.getTotal();
assertThat(total, is(closeTo(12.53, 0.0001)));

The second number parameter is the amount of approximation error you are willing to accept for the test to pass.

BigDecimals

BigDecimal objects can sometimes be tricky due to two instances having the same value, but different scales --- they are considered to be different values (as determined by the equals method) if they have different scales.

Instead, you should use the compareTo method to compare BigDecimals (the method will return 0 if the numbers have the same value, regardless of scale). Hamcrest has a handy comparesEqualTo method that works well here:

BigDecimal bd1 = new BigDecimal("10.0");
BigDecimal bd2 = new BigDecimal("10.00");

assertThat(bd1, is(bd2));  // this test will fail because the numbers do not have the same scale

assertThat(bd1, comparesEqualTo(bd2));  // this test should pass

These examples should cover everything that you need in {{$:/ou/parameters/Paper Code}}. You may also want to take a look at the following quick tutorial which has examples of some features that were not covered above:

https://www.baeldung.com/java-junit-hamcrest-guide

You might also find the following API document handy --- it shows all of the available matcher methods that Hamcrest provides:

http://hamcrest.org/JavaHamcrest/javadoc/2.2/org/hamcrest/Matchers.html