Hamcrest
01 / 02

Core Matchers & assertThat

Hamcrest: Core Matchers & assertThat

Hamcrest is a library of composable matcher objects for writing expressive, readable test assertions -- it doesn't run tests itself, it plugs into assertThat() calls from JUnit, TestNG, or similar test runners.

assertThat and Basic Matchers

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

@Test
void basicMatchers() {
    int result = calculate();

    // is() is a pure readability wrapper -- is(5) == is(equalTo(5))
    assertThat(result, is(5));
    assertThat(result, equalTo(5));

    // On failure, produces a specific message automatically:
    // "expected <5> but was <3>" -- unlike assertTrue(result == 5),
    // which would just report "expected true but was false"

    assertThat(result, greaterThan(0));
    assertThat(result, not(equalTo(0)));

    String name = getName();
    assertThat(name, containsString("Ali"));   // substring match
    assertThat(name, startsWith("Al"));
    assertThat(name, equalToIgnoringCase("ALICE"));

    Double pi = computePi();
    // Floating point equality is unreliable -- use a tolerance
    assertThat(pi, closeTo(3.14159, 0.001));
}

Combinators: allOf, anyOf, not

@Test
void combinedMatchers() {
    int age = getAge();

    // All conditions must match
    assertThat(age, allOf(greaterThan(0), lessThan(120)));

    // At least one condition must match
    assertThat(status, anyOf(equalTo("ACTIVE"), equalTo("PENDING")));

    // Negation
    assertThat(list, not(empty()));
    assertThat(value, not(nullValue()));

    // Type checking
    assertThat(exception, instanceOf(IllegalArgumentException.class));

    // Testing a Java Bean property via reflection
    assertThat(person, hasProperty("name", equalTo("Alice")));
}

Why Matcher Assertions Over Plain Booleans

  • assertThat(value, greaterThan(5)) reports "expected a value greater than <5> but was <3>" -- assertTrue(value > 5) just reports "expected true but was false", losing context.

  • Matchers are composable -- allOf/anyOf/not build complex conditions readably instead of a tangled boolean expression.

  • Prefer specific matchers over generic ones (notNullValue(), anything()) -- weak assertions pass even when the actual value is wrong, giving false confidence.

  • JUnit 5 dropped its bundled Hamcrest dependency -- add org.hamcrest:hamcrest explicitly to keep using assertThat() with Hamcrest matchers.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free