Hamcrest auto-matcher

Automatic hamcrest matcher for model classes

License

License

Categories

Categories

Auto Application Layer Libs Code Generators
GroupId

GroupId

org.itsallcode
ArtifactId

ArtifactId

hamcrest-auto-matcher
Last Version

Last Version

0.5.0
Release Date

Release Date

Type

Type

pom.sha512
Description

Description

Hamcrest auto-matcher
Automatic hamcrest matcher for model classes
Project URL

Project URL

https://github.com/itsallcode/hamcrest-auto-matcher
Source Code Management

Source Code Management

https://github.com/itsallcode/hamcrest-auto-matcher

Download hamcrest-auto-matcher

Dependencies

runtime (1)

Group / Artifact Type Version
org.hamcrest : hamcrest-all jar 1.3

Project Modules

There are no modules declared in this project.

hamcrest-auto-matcher

Automatic hamcrest matcher for model classes for Java 11

Build Quality Gate Status Coverage Maven Central

Why use hamcrest-auto-matcher?

Writing a hamcrest matcher for your model classes by extending TypeSafeDiagnosingMatcher is a good idea, because it gives you a readable diff of actual and expected property values. But doing it by hand is tedious and hard to get right, especially for classes with many properties:

  • It is easy to make mistakes in the matches() method.
  • It requires lot's of boiler plate code.
  • Good layout of actual and expected property values is hard to get right.
  • Each property occurs in multiple places which violates the DRY principle.

Requirements

Java 11

How to use hamcrest-auto-matcher in your project

Setup dependencies

Gradle

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'org.itsallcode:hamcrest-auto-matcher:0.5.0'
}

Maven

<dependency>
    <groupId>org.itsallcode</groupId>
    <artifactId>hamcrest-auto-matcher</artifactId>
    <version>0.5.0</version>
    <scope>test</scope>
</dependency>

Using AutoMatcher

Assume you have two model classes DemoModel and DemoAttribute:

public class DemoModel {
    private final int id;
    private final String name;
    private final DemoAttribute attr;
    private final List<DemoModel> children;
    private final String[] stringArray;
    private final Long longVal;

    public DemoModel(int id, String name, Long longVal, DemoAttribute attr, String[] stringArray,
            List<DemoModel> children) {
        this.id = id;
        this.name = name;
        this.longVal = longVal;
        this.attr = attr;
        this.stringArray = stringArray;
        this.children = children;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public DemoAttribute getAttr() {
        return attr;
    }

    public List<DemoModel> getChildren() {
        return children;
    }

    public String[] getStringArray() {
        return stringArray;
    }

    public Long getLongVal() {
        return longVal;
    }

    @Override
    public String toString() {
        return "DemoModel [id=" + id + ", name=" + name + ", attr=" + attr + ", children=" + children + ", stringArray="
                + Arrays.toString(stringArray) + ", longVal=" + longVal + "]";
    }
}

public class DemoAttribute {
    private final String value;

    public DemoAttribute(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "DemoAttribute [value=" + value + "]";
    }
}

Use AutoMatcher.equalTo() to create a matcher for your expected model instance. This will use reflection to determine expected property values based on getter methods:

DemoModel expected = ...;
DemoModel actual = ...;
assertThat(actual, AutoMatcher.equalTo(expected));

Example mismatch report:

Expected: {id=<4711>, longVal=null, name="name1", attr=null, stringArray=null, children=null}
     but: {longVal was <42L>}

Using ConfigurableMatcher

If AutoMatcher does not work for your model classes, you can still use ConfigurableMatcher and MatcherConfig which allows you to specify properties and custom matchers explicitly but is much easier to use than TypeSafeDiagnosingMatcher.

public class DemoModelMatcher {
    public static Matcher<DemoModel> equalTo(DemoModel expected) {
        final MatcherConfig<DemoModel> config = MatcherConfig.builder(expected)
                .addEqualsProperty("id", DemoModel::getId)
                .addEqualsProperty("longVal", DemoModel::getLongVal)
                .addEqualsProperty("name", DemoModel::getName)
                .addProperty("attr", DemoModel::getAttr, DemoAttributeMatcher::equalTo)
                .addEqualsProperty("stringArray", DemoModel::getStringArray)
                .addIterableProperty("children", DemoModel::getChildren, DemoModelMatcher::equalTo)
                .build();
        return new ConfigurableMatcher<>(config);
    }
}

Also see DemoModelMatcher as an example.

Development

$ git clone https://github.com/itsallcode/hamcrest-auto-matcher.git
$ ./gradlew check
# Test report: build/reports/tests/index.html

Using eclipse

Import into eclipse using buildship.

Generate license header for added files

$ ./gradlew licenseFormat

Publish to Maven Central

  1. Add the following to your ~/.gradle/gradle.properties:

    ossrhUsername=<your maven central username>
    ossrhPassword=<your maven central passwort>
    
    signing.keyId=<gpg key id (last 8 chars)>
    signing.password=<gpg key password>
    signing.secretKeyRingFile=<path to secret keyring file>
  2. Increment version number in build.gradle, update version in README.md, commit and push.

  3. Run the following command:

    $ ./gradlew clean check build publish closeAndReleaseRepository --info
  4. Create a new release on GitHub.

  5. After some time the release will be available at Maven Central.

org.itsallcode

It's all code

Community of everything-as-code enthusiasts

Versions

Version
0.5.0