Skip navigation links

Hamcrest Composites 1.3.0 API

Provides Matchers for comparing complex Java objects with better testability.

See: Description

Packages 
Package Description
org.cornutum.hamcrest
For more explanation of these classes, see the Overview.
Provides Matchers for comparing complex Java objects with better testability.

What Is It?

hamcrest-composites is a collection of Hamcrest matchers for comparing complex Java objects with better testability. They apply to what might be called "composite objects", i.e. iterable containers (in all their various forms) and objects whose properties define a nested tree of object references. For Java programmers, hamcrest-composites leverages the power of Java functional interfaces to make assertions about composite objects more thorough, easier to express, and easier to debug.

Why Composite Matchers?

With standard Hamcrest, verifying that two objects are equals is easy. But comparing the full tree of object property values is much more involved and not directly supported. Although such "deep matching" is needed for testing, it's often impossible (and almost always wrong!) to implement it using equals. Instead, hamcrest-composites makes it much easier to implement deep matching using a "composite matcher". Similarly, because standard Hamcrest has always been a bit weak for comparing collections and arrays, hamcrest-composites adds more robust matchers for all types of iterable containers.

Consider the case of a Drawing object that contains a collection of Shape instances, each of which has complex properties, such as a Color. Consider the tests for a system that manipulates Drawing objects. How would a test verify that a Drawing produced by the system contains all of the expected content? With hamcrest-composites, it can be as simple as this:

Drawing expected = ...
Drawing produced = ...

// Compare the complete tree of properties using a DrawingMatcher that extends BaseCompositeMatcher.
assertThat( produced, matches( new DrawingMatcher( expected)));
And defining a composite matcher for Drawing instances can be as simple as this:
public class DrawingMatcher extends BaseCompositeMatcher
  {
  public DrawingMatcher( Drawing expected)
    {
    super( expected);

    // Compare values for a simple scalar property.
    expectThat( valueOf( "name", Drawing::getName).matches( Matchers::equalTo));

    // Compare values for an Iterable container property, comparing the complete tree of properties for each member.
    expectThat( valueOf( "elements", Drawing::getElements).matches( containsMembersMatching( ShapeMatcher::new)));

    // Compare values for an array property.
    expectThat( valueOf( "tags", Drawing::getTags).matches( Composites::containsElements));
    }
  }
But what if the composite match fails? For example, what if the produced Drawing mostly matches, except that one of the shapes has the wrong color? Then you'd see an assertion error message that pinpoints the discrepancy like this:
Expected: Drawing[Blues] matching elements=Iterable containing CIRCLE matching color=<Color[0,0,255]>
     but: was <Color[255,0,0]>

How Does It Work?

Need More Examples?

For more examples of hamcrest-composites matchers in action, see the unit tests, as described on GitHub in Cornutum/hamcrest-composites/README.md
Skip navigation links

Copyright © 2022 The Cornutum Project. All rights reserved.