- By André Guelfi Torres
 - ·
 - Posted 08 Apr 2019
 
Every time I was trying to test an object's properties I was neither satisfied writing very verbose tests nor in using some of the out of the box hamcrest matchers. Although using the matchers was a big help, I never managed to make them read the way I wanted.
Another thing that was very important to me, I wanted to have a single assertion per method and a very descriptive description if the test did not pass.
I've decided to write my own matcher and hopefully it will be useful to other people. So, that's what I've done:
Hamcrest matcher to match multiple attributes of an object within a single assertion.
// Static imports
import static org.craftedsw.beanpropertymatcher.matcher.BeanMatcher.has;
import static org.craftedsw.beanpropertymatcher.matcher.BeanPropertyMatcher.property;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
// Imagine that you have a method that returns an object Person
Person person = new Person();
person.setFirstName("Sandro");
person.setAge(25);
person.setLastName("Mancuso");
// Then you can test it like that
assertThat(person, has(
                        property("firstName", equalTo("Another dude")),  // Mistmatch
                        property("age", greaterThan(18)),  // Use any matcher
                        property("lastName", equalTo("Mancuso"))));
Hamcrest matcher to match multiple attributes of an object within a single assertion.
NOTE: Make sure you are using org.hamcrest.MatcherAssert.assertThat instead of the JUnit one.
If you run this test, you will get a message like
java.lang.AssertionError:
     Expected: property "firstName" = "Another dude"
     but: property "firstName" was "Sandro"
Now, change the age check to
property("age", greaterThan(60))
And you should get:
Testing object graphs
You can also do this
Person person = new Person();
    person.setFirstName("Sandro");
    person.setAge(35);
    Country uk = new Country();
    uk.setName("United Kingdom");
    Address address = new Address();
    address.setPostcode("1234556");
    address.setCity("London");
    address.setCountry(uk);
    person.setAddress(address);
    assertThat(person, has(
                            property("firstName", equalTo("Sandro")),
                            property("age", greaterThan(18)),
                            property("address.city", equalTo("London")),
                            property("address.postcode", equalTo("1234556")),
                            property("address.country.name", equalTo("United Kingdom"))));
I use a combination of two matchers to do that:
BeanMatcher: Provides the "has" method responsible to group all the property matchers.
BeanPropertyMatcher: Provides the "property" method.
I expect to make more changes to them, so for the most up-to-date version, please check BeanMatcher on my github account.
Enjoy!!!
Software is our passion.
We are software craftspeople. We build well-crafted software for our clients, we help developers to get better at their craft through training, coaching and mentoring, and we help companies get better at delivering software.