Platinum Partner
java,testing,tips and tricks

Testing Multiple Properties With a Single Assertion

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:

BeanMatcher

Hamcrest matcher to match multiple attributes of an object within a single assertion.

How to use it

// 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"))));

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:

java.lang.AssertionError:
        Expected: property "firstName" = "Another dude" , property "age" = a value greater than <60>
        but: property "firstName" was "Sandro" , property "age" <25> was less than <60>

 

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.
 

 

 

Published at DZone with permission of {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}