Hamcrest: Collection Matchers & Custom Matchers
Collection Matchers
@Test
void collectionMatchers() {
List<String> fruits = List.of("apple", "banana", "cherry");
assertThat(fruits, hasSize(3));
assertThat(fruits, hasSize(greaterThan(0))); // composes with other matchers
// hasItem: at least this element exists, anywhere, ignoring the rest
assertThat(fruits, hasItem("banana"));
assertThat(fruits, hasItems("apple", "cherry"));
// contains: the ENTIRE collection must match, in this exact order --
// much stricter than hasItem
assertThat(fruits, contains("apple", "banana", "cherry"));
// containsInAnyOrder: exact elements required, order doesn't matter --
// appropriate for a Set or non-deterministic iteration order
assertThat(Set.of("a", "b", "c"), containsInAnyOrder("c", "b", "a"));
assertThat(List.of(), is(empty()));
assertThat(fruits, everyItem(not(nullValue())));
}Writing a Custom Matcher
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
// A domain-specific matcher: is this order actually valid to submit?
public class IsValidOrder extends TypeSafeMatcher<Order> {
@Override
protected boolean matchesSafely(Order order) {
return !order.getItems().isEmpty()
&& order.getTotal().compareTo(BigDecimal.ZERO) > 0
&& order.getShippingAddress() != null;
}
@Override
public void describeTo(Description description) {
description.appendText("a valid order with items, a positive total, and a shipping address");
}
@Override
protected void describeMismatchSafely(Order order, Description mismatchDescription) {
mismatchDescription.appendText("was ").appendValue(order);
}
public static IsValidOrder isValidOrder() {
return new IsValidOrder();
}
}
// Usage -- reads naturally, and failures explain exactly what was expected
import static com.example.matchers.IsValidOrder.isValidOrder;
@Test
void orderShouldBeValid() {
Order order = buildOrder();
assertThat(order, isValidOrder());
}Hamcrest vs AssertJ
Both solve the same problem: more expressive, better-diagnostic assertions than raw assertEquals/assertTrue.
Hamcrest: assertThat(list, hasSize(3)) -- many separately-imported static matcher functions.
AssertJ: assertThat(list).hasSize(3).contains("a") -- fluent method chaining, often more IDE-autocomplete-discoverable per type.
Both integrate with JUnit 4/5 and TestNG the same way -- picking one is largely a team-style preference, not a functional difference.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free