Code Monkey home page Code Monkey logo

hamcrest-bean's Introduction

Hamcrest Bean Build Status Coverage Status

A Java library which provides a hamcrest matcher for matching objects and graphs which follow the Java beans standard.

Licensed under BSD License.

What is Hamcrest Bean?

Hamcrest Bean is an extension library for the Java Hamcrest matcher library which provides Matcher implementations for performing deep object graph matching of java beans

Downloads

You can obtain Hamcrest Bean binaries from maven central. To include your project in:

A maven project

<dependency>
    <groupId>org.exparity</groupId>
    <artifactId>hamcrest-bean</artifactId>
    <version>1.0.12</version>
</dependency>

A project which uses ivy for dependency management

<dependency org="org.exparity" name="hamcrest-bean" rev="1.0.12"/>

Binaries

Hamcrest Bean has a single binary, hamcrest-bean.jar, which contains all the date matchers. Sources and JavaDoc jars are available.

Usage

The matchers are exposed as static methods on the BeanMatchers class. For Example

MyObject object = new MyObject();
MyObject saved = dao.save(object);
MatcherAssert.assertThat(save, BeanMatchers.theSameAs(object));

or after static importing

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object));

The matcher allows paths, properties, and types to be excluded from the match if they're expected to be different. For example to exclude a path

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).excludePath("MyObject.Id"));

or to exclude a property;

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).excludeProperty("Id"));

or to exclude a path;

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).excludeType(String.class));

The matcher allows paths, properties, and types to use alternate matchers if you want finer control over the match. For example to override the match for a path

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).comparePath("MyObject.Name", new IsEqualIgnoreCase()));

or to override the match for a property;

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).compareProperty("Name", new IsEqualIgnoreCase()));

or to override the match for a path;

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).compareType(String.class, new IsEqualIgnoreCase()));

The matcher also supports using other Java Hamcrest matchers to act as comparators.For example.

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).comparePath("MyObject.Name", Matchers.startsWith("S")));

or to override the match for a property;

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).compareProperty("Name", Matchers.startsWith("S")));

or to override the match for a path;

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object).compareType(String.class, Matchers.notNullValue()));

The matcher exposes a fluent interface so multiple exclusions or overrides can be provider. For example

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameAs(object)
                     .compareType(String.class, new IsEqualIgnoreCase())
                     .excludeProperty("Id")
                     .excludePath("MyObject.Name"));

If you only want to include bean properties, those which have both a getter and setter pair, in the comparison then use the theSameBeanAs matcher. For example

MyObject object = new MyObject();
MyObject saved = dao.save(object);
MatcherAssert.assertThat(save, BeanMatchers.theSameBeanAs(object));

or after static importing

MyObject object = new MyObject();
MyObject saved = dao.save(object);
assertThat(save, theSameBeanAs(object));

The library includes several built in overrides for the comparison

  • IsComparable - Test if the objects are comparable
  • IsEqual - Test if the objects are equals
  • IsEqualIgnoreCase - Test if two string objects are equal regardless of case
  • HasPattern - Test if the strings match the pattern
  • Excluded - Exclude a property, type, or method from the comparison
  • IsEqualDate - Test it two date objects are equal date but not time or millisecond portion
  • IsEqualDateTime - Test it two date objects are equal date and time but no millisecond portion
  • IsEqualTimestamp - Test it two date objects are equal timestamps
  • Matches - Test if a property, type, or method are equal using a hamcrest matcher

The Javadocs include examples on all methods so you can look there for examples for specific methods.

Source

The source is structured along the lines of the maven standard folder structure for a jar project.

  • Core classes [src/main/java]
  • Unit tests [src/test/java]

The source includes a pom.xml for building with Maven

Release Notes

Changes 1.0.11 -> 1.0.12

  • Fix Issue #7 Issues comparing enum values Changes 1.0.10 -> 1.0.11
  • Fix Issue #6 and support comparing nulls in arrays Changes 1.0.9 -> 1.0.10
  • Add IsEqual date comparators and add BeanComparators static factory Changes 1.0.8 -> 1.0.9
  • Add theSameBeanAs matchers Changes 1.0.4 -> 1.0.8
  • Fix issue 4 comparing null nested objects Changes 1.0.3 -> 1.0.4
  • Strongly type PropertyComparator

Acknowledgements

Developers:

  • Stewart Bissett
  • Simon Birt

Thanks to the developers at Java Hamcrest. Without their hardwork and core libraries there'd be nothing to be extend and we be stuck with old school, non-declarative, non-reusable, assertions.

hamcrest-bean's People

Contributors

stewbis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

hamcrest-bean's Issues

ClassCastException whilst comparing lists of inner classes

package com.trafigura.itest.features.trade.capture;

import org.exparity.hamcrest.beans.TheSameAs;
import org.hamcrest.MatcherAssert;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.List;

public class TestSameAsMatcher {

@Test
public void testMultipleElements() {
    MatcherAssert.assertThat(aClassWithMultipleOuter(), TheSameAs.theSameAs(aClassWithMultipleOuter()));
}

public AClass aClassWithMultipleOuter() {
    AClass aClass = new AClass();
    aClass.getOuterClassList().add(new OuterClass());
    aClass.getOuterClassList().add(new OuterClass());
    return aClass;
}

public class AClass {
    private List<OuterClass> outerClassList = new ArrayList<>();

    public List<OuterClass> getOuterClassList() {
        return outerClassList;
    }
}

public class OuterClass {
    private InnerClass innerClass = new InnerClass();

    class InnerClass {
    }
}

}

Problem comparing enum values

  • I have come across what looks like incorrect behaviour to me. I was using a library class which ultimately uses hamcrest-bean's TheSameAs.comparesSafely() to compare two object graphs as part of unit testing.
  • A unit test seemed to be passing inappropriately, because one attribute value in the two object graphs being compared differed, but was found to be the same by TheSameAs.compareObjects():
  • The attribute in question was a Java enum, and in one object graph had, for example, VALUE_A, whilst in the other it had the value VALUE_B. The types did not differ, just the values. However, TheSameAs.compareObjects() did not find the values to differ, and so TheSameAs.addMismatch() is not called.
  • Perhaps TheSameAs.compareObjects() should be modified to provide special comparison behaviour for enum values?

Problem when comparing String[] which contain null values

Hello, I have a small JavaBean + a Test that fails. The basic idea is that I read the data from DB or from JSON and then I compare them. This is used by our testing framework. It seems that when both indexes of fieldData[] are null, the matcher throws an error, thus preventing me to properly use it. FieldData[3] has a null value on both objects. This might be an edge case. If so, please close the issue. I just want to understand the behavior of the matcher.
JavaBean below:


import java.util.Arrays;

/**
 * Java Bean class for table "list_person".
 */
public class MyCustomJavaBean implements Comparable<MyCustomJavaBean> {

    private Long listPersonId;

    private String[] fieldData = new String[3];

    public MyCustomJavaBean() {

    }

    public MyCustomJavaBean(Long listPersonId, String[] fieldData) {
        this.listPersonId = listPersonId;
        this.fieldData = fieldData;
    }

    /**
     * @return the listPersonId
     */
    public Long getListPersonId() {
        return listPersonId;
    }

    /**
     * @param listPersonId the listPersonId to set
     */
    public void setListPersonId(Long listPersonId) {
        this.listPersonId = listPersonId;
    }

    /**
     * @return the fieldData
     */
    public String getFieldData(Integer index) {
        return fieldData[index - 1];
    }

    /**
     * Needed for comparing two objects.
     * @return the fieldData
     */
    public String[] getFieldData() {
        return fieldData;
    }

    /**
     * @param index
     * @param data
     */
    public void setFieldData(Integer index, String data) {
        this.fieldData[index - 1] = data;

    }

    /**
     * @param fieldData
     */
    public void setFieldData(String[] fieldData) {
        this.fieldData = new String[40];
        Integer len = fieldData.length;
        for (Integer i = 0; i < 3; i++) {
            String element;
            if (i < len) {
                element = fieldData[i];
            } else {
                element = null;
            }
            this.fieldData[i] = element;
        }
    }

    /*
     * (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "ListPerson [listPersonId=" + listPersonId + "fieldData = " + fieldDataToString() + "]";
    }

    private String fieldDataToString() {
        StringBuilder sb = new StringBuilder("[size = " + fieldData.length + ", values =  ");
        for (String value : fieldData) {
            sb.append(value).append(", ");
        }
        sb.append("]");
        return sb.toString();
    }

    /*
     * (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Arrays.hashCode(fieldData);
        return result;
    }

    /*
     * (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MyCustomJavaBean other = (MyCustomJavaBean) obj;
        if (!Arrays.equals(fieldData, other.fieldData))
            return false;
        return true;
    }

    @Override
    public int compareTo(MyCustomJavaBean listPerson) {
        if (listPerson == null) {
            return 1;
        }
        if (listPerson.listPersonId == null) {
            return 0;
        } else {
            return listPersonId.compareTo(listPerson.listPersonId);
        }
    }
}

Test class below:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;

import static org.exparity.hamcrest.beans.TheSameAs.theSameAs;

import java.util.Arrays;

public class Main {

    @Rule
    public ErrorCollector errorCollector = new ErrorCollector();

    @Test
    public void simpleTest() {

        String[] actualFieldData = new String[3];
        String[] expectedFieldData = new String[3];

        actualFieldData = new String[] {"John", "Doe", null};
        MyCustomJavaBean actual = new MyCustomJavaBean(new Long(1), actualFieldData);

        expectedFieldData = new String[] {"Jane", "Dove", null};
        MyCustomJavaBean expected = new MyCustomJavaBean(new Long(1), expectedFieldData);

        errorCollector.checkThat(actual, theSameAs(expected));

        errorCollector.checkThat(Arrays.asList(actual), theSameAs(Arrays.asList(expected)));
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.