Working with Rest Assured Matchers

Working with Rest Assured Matchers

What are matchers?

The main goal when testing the restful api is to validate that the api is working according the requirements. In order to achieve this, the retrieved response has to be validated. In many cases JUnit Assert is used for validating the end result, but when validating the response from an endpoint you may need to validate several parameters. This kind of assertion can be simplified when using matchers:

Assert.assertEquals(expected1, actual1);
Assert.assertEquals(expected2, actual2);
Assert.assertEquals(expected3, actual3);
Assert.assertEquals(expected4, actual4);
Assert.assertEquals(expected5, actual5);

Matchers are similar to JUnit Assert , but the difference is that Matchers allow more possibilities when asserting the result, and allowing the code to be more readable.

Let’s get started

In this section I’m going to describe one of the most used matchers when validating the response. The matchers that are used for this example are the following: hasItem, hasItems, anyOf, allOf, anything, nullValue, equalTo.

The JSON object/s that are going to be asserted in this example are going to be in the following way:


"teams": [
    {
        "_links": {
            "self": {
                "href": "http://api.football-data.org/v1/teams/1783"
            },
            "fixtures": {
                "href": "http://api.football-data.org/v1/teams/1783/fixtures"
            },
            "players": {
                "href": "http://api.football-data.org/v1/teams/1783/players"
            }
        },
        "name": "CR Flamengo",
        "code": null,
        "shortName": "Flamengo",
        "squadMarketValue": null,
        "crestUrl": "https://upload.wikimedia.org/wikipedia/en/c/c9/Flamengo_logo.svg"
    }
]

Matchers hasItem and hasItems

hasItem matcher is used to validate that at least one item is matched by specified itemMatcher. For example:


@Then("^Validate the team name \"(.*)\" with hasItem matcher$")
public void thenValidateTheTeamName(String teamName) {
    apiHelper.getEndpoint().readResponse().body("teams.name", hasItem(teamName));
}

With this portion of the code it is validated that the array of team names contain team with specific name. The names of each team are filtered with JSONPath, and they are placed inside an array. In this case when the matcher hasItem(“CR Flamengo”) is satisfied, the validation is successful.

In case when we want to validate that more than one team is present in the response, hasItems matcher should be used. Here is an example:


@Then("^Validate the team name \"(.*)\" with hasItems matcher$")
    public void thenValidateTheTeamNameWithHasItemsMatcher(String teamNames) {
        apiHelper.getEndpoint()
                 .readResponse()
                 .body("teams.name", hasItems(teamNames.split(";")));
}

In this case the team names are separated with semi-colon, and by calling the split function the string is converted into an array. When using hasItems matcher we have validated that the expected team names are present in the array of team names.

Matchers anyOf and allOf

In cases when the assertion does not has to satisfy all matchers, or the assertion has to satisfy some of the matchers anyOf and allOf matcher can be used. Here is an example validating the team names using the any of matcher.


@Then("^Validate the team name \"(.*)\" with anyOf matcher$")
    public void thenValidateTheTeamNameWithAnyOfMatcher(String teamNames) {
        String[] teamNamesArray = teamNames.split(";");
        apiHelper.getEndpoint()
                 .readResponse()
                 .body("teams[0].name", 
                       anyOf(is(teamNamesArray[0]), is(teamNamesArray[1])));
}

In this example the validation is done on the first team name from the teams JSON array.
teamNamesArray contains two team names, one which is equal to the expected team name, and another which is not equal to the team name. The anyOf matcher is successful when one of the matchers is satisfied.

In case when we want all the matchers to be satisfied for a specific validation allOf matcher should be used. Here is an example


@Then("^Validate the team name \"(.*)\" with allOf matcher$")
    public void thenValidateTheTeamNameWithAllOfMatcher(String teamName) {
        apiHelper.getEndpoint()
                 .readResponse()
                 .body("teams[0].name", 
                        allOf(not(isEmptyOrNullString()), equalTo(teamName)));
}

With the following example we are validating that the name of the first team is not null or empty, and the name of the team is equal to the expected name. When using allOf matcher all matchers has to be satisfied, if one matcher has failed, the total assertion is going to fail.

Matcher anything and nullValue

There are cases when we need to validate that a property from the JSON object has value, or it is null. This can be achieved by using anything or nullValue matchers. Here is an example validating that the team name has any value.


@Then("^Validate that the team has anything$")
    public void thenValidateThatTheTeamHasAnything() {
        apiHelper.getEndpoint().readResponse().body("teams.name", anything());
}

The anything matcher always matches, regardless of the examined object. In the following case the assertion is going to be successful regardless of the team name that is going to be retrieved.

In cases we need to validate the JSON parameter value is null we can use the nullValue() matcher. Here is an example validating the team code value is null.


@Then("^Validate the team code is null$")
    public void thenValidateTheTeamCodeIsNull() {
        apiHelper.getEndpoint()
                 .readResponse()
                 .body("teams.code", everyItem(is(nullValue())));
}

With the following assertion is asserted that the every team code is null, in this case if one team code is not null the assertion is going to fail. If we want to assert that the JSON parameter value is not null, we can use nullValue() matcher with combination of not matcher like not(nullValue()).

Matcher equalTo

The matcher equalTo is used to assert that JSON property value is equal to the expected value. Here is an example using equalTo matcher.


@Then("^Validate the team name \"(.*)\" with equalTo matcher$")
    public void thenValidateTheTeamNameWithEqualToMatcher(String teamName) {
        apiHelper.getEndpoint()
                 .readResponse()
                 .body("teams[0].name", equalTo(teamName));
}

With the following example it is asserted the first team name is going to be equal to the expected value.

Chaining matchers

Rest assured allows chaining matchers for specific validation of the retrieved response. Here is an example using chained matcher with rest assured:


@Then("^Validate the team name \"(.*)\" and short name \"(.*)\"$")
public void thenValdiateTheTeamNameAndShortName(String teamName, String teamShortName) {
        apiHelper.getEndpoint().readResponse()
                .body("teams[0].name", equalTo(teamName))
                .body("teams[0].shortName", equalTo(teamShortName));
}

With the example above it is validated that the name and short name of the first team is equal to the expected value. This is simple example, but by chaining matchers could be asserted more complex scenarios.

Conclusion

Using matchers decreases the complex code logic using for loops to parse the response for validation, and decreases the complexity for validating the JSON properties. Following this approach the automation tester, could use specific or combination of matchers in order to validate the scenario under test. The whole  code describing the usage of matchers is described in the following link.

3 thoughts on “Working with Rest Assured Matchers

  1. Pingback: Testing Bits – August 26th – September 1st, 2018 | Testing Curator Blog

  2. Pingback: Java Testing Weekly 36 / 2018

  3. Bas Dijkstra

    Hi Darjan,

    thanks for this overview, it’s well written and it has clear examples.

    What might be useful to mention is that these matchers are not something that’s built into REST Assured itself, they are part of a library called Hamcrest. Here’s the JavaDoc for the latest version: http://hamcrest.org/JavaHamcrest/javadoc/1.3/ (all the available matchers can be found in org.hamcrest.core).

Leave a Reply

Your email address will not be published. Required fields are marked *