1. Overview

Hamcrest provides matchers for making unit test assertions simpler and more legible. You can get started exploring some of the available matchers here.

In this quick tutorial, we’ll dive deeper into object matchers.

2. Setup

To get Hamcrest, we just need to add the following Maven dependency to our pom.xml:

The latest Hamcrest version can be found over on Maven Central.

3. Object Matchers

Object matchers are meant to perform checks over object’s properties.

Before looking into the matchers, we’ll create a couple of beans to make the examples simple to understand.

Our first object is called Location and has no properties:

public class Location {}

We’ll name our second bean City and add the following implementation to it:

public class City extends Location {
    
    String name;
    String state;

    // standard constructor, getters and setters

    @Override
    public String toString() {
        if (this.name == null && this.state == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append("Name: ");
        sb.append(this.name);
        sb.append(", ");
        sb.append("State: ");
        sb.append(this.state);
        sb.append("]");
        return sb.toString();
    }
}

Note that City extends Location. We’ll make use of that later. Now, let’s start with the object matchers!

3.1. hasToString

As the name says, the hasToString* method verifies that certain object has a toString method that returns a specific *String:

@Test
public void givenACity_whenHasToString_thenCorrect() {
    City city = new City("San Francisco", "CA");
    
    assertThat(city, hasToString("[Name: San Francisco, State: CA]"));
}

So, we’re creating a City and verifying that its toString method returns the String that we want. We can take this one step further and instead of checking for equality, check for some other condition:

@Test
public void givenACity_whenHasToStringEqualToIgnoringCase_thenCorrect() {
    City city = new City("San Francisco", "CA");

    assertThat(city, hasToString(
      equalToIgnoringCase("[NAME: SAN FRANCISCO, STATE: CA]")));
}

As we can see, hasToString is overloaded and can receive both a String or a text matcher as a parameter. So, we can also do things like:

@Test
public void givenACity_whenHasToStringEmptyOrNullString_thenCorrect() {
    City city = new City(null, null);
    
    assertThat(city, hasToString(emptyOrNullString()));
}

You can find more information on text matchers here. Now let’s move to the next object matcher.

3.2. typeCompatibleWith

This matcher represents an is-a relationship. Here comes our Location superclass into play:

@Test
public void givenACity_whenTypeCompatibleWithLocation_thenCorrect() {
    City city = new City("San Francisco", "CA");

    assertThat(city.getClass(), is(typeCompatibleWith(Location.class)));
}

This is saying that City is-a Location, which is true and this test should pass. Also, if we wanted to test the negative case:

@Test
public void givenACity_whenTypeNotCompatibleWithString_thenCorrect() {
    City city = new City("San Francisco", "CA");

    assertThat(city.getClass(), is(not(typeCompatibleWith(String.class))));
}

Of course, our City class is not a String.

Finally, note that all Java objects should pass the following test:

@Test
public void givenACity_whenTypeCompatibleWithObject_thenCorrect() {
    City city = new City("San Francisco", "CA");

    assertThat(city.getClass(), is(typeCompatibleWith(Object.class)));
}

Please remember that the matcher is consists of a wrapper over another matcher with the purpose of making the whole assertion more readable.

4. Conclusion

Hamcrest provides a simple and clean way of creating assertions. There is a wide variety of matchers that make every developer’s life simpler as well as every project more readable.

And object matchers are definitely a straightforward way of checking class properties.

As always, you’ll find the full implementation over on the GitHub project.


» 下一篇: Checkstyle简介