DEV Community

Cover image for How to Create and Use a Custom ResultMatcher for Date Testing with MockMvc
Willian Ferreira Moya
Willian Ferreira Moya

Posted on • Originally published at springmasteryhub.com

How to Create and Use a Custom ResultMatcher for Date Testing with MockMvc

In this tutorial, you will learn how to create a custom ResultMatcher for MockMvc, to suit your project needs.

Imagine you are testing an API and the response contains a date. And you want to check if the response date is valid.

So you have a test assertion that checks for an exact date and time. But for some reason, this result can vary over time. For some reasons:

  • Maybe your machine has a different timezone from what’s used in the server.
  • Maybe some parts of your code can use different time zones.
  • Maybe your code has a business rule that has to calculate a date and time that can vary in a range.
  • Maybe you are using LocalDateTime.now() and you cannot mock using the Clock.
  • Or any specific other date manipulation or configuration that your project has.

When you run your tests you get errors like this, you check for the LocalDateTime.now() but the result is a few seconds later.

Expected: is "2024-01-11T12:37:03.1"
but: was "2024-01-11T12:38:21.1"
Enter fullscreen mode Exit fullscreen mode

Or you have a time zone issue that makes everything 3 hours behind:

Expected: is "2023-03-07T20:18:57"
but: was "2023-03-07T17:18:57"
Enter fullscreen mode Exit fullscreen mode

One solution for that (there are more solutions, maybe some better ones) is to create a custom ResultMatcher. That can check if the result date from an API response is in a range.

How to use a custom result matcher to fix this issue?

If we are checking the MockMvc the code should look like this:

mvc.perform(get("/product/{}",productId).contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.date", is("2023-03-07T17:18:57")));
Enter fullscreen mode Exit fullscreen mode

As we said, the problem with this implementation is that the assertion is by the exact date and time.

And our time can vary a little bit, so it’ll break our test.

Writing a custom result matcher will enable you to do custom checks as you need.

You can write a result matcher that checks if the response date is in a range that you specify.

Example of a custom result matcher for date range validation:

public static ResultMatcher isDateTimeInRange(String path, String startDateStr, String endDateStr) {
        LocalDateTime startDate = LocalDateTime.parse(startDateStr, formatter);
        LocalDateTime endDate = LocalDateTime.parse(endDateStr, formatter);
        return mvcResult -> {
            String contentAsString = mvcResult.getResponse().getContentAsString();
            LocalDateTime checkoutDate = LocalDateTime.parse(JsonPath.read(contentAsString, path), formatter);
            if (!(checkoutDate.isAfter(startDate) && checkoutDate.isBefore(endDate))) {
                throw new AssertionError(String.format("Date: %s is not between %s and %s", checkoutDate, startDate, endDate));
            }
        };
    }
Enter fullscreen mode Exit fullscreen mode

This code allows us to send a start and end range and the date format for the date we’re working.

This will enable us to write our logic to check if the date is in range!

How to use your custom result matcher in your test

mvc.perform(get("/product/{}",productId).contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(status().isOk())
                .andExpect(isDateTimeInRange("$.date",
                                "2019-03-07T13:18:57",
                                "2019-03-07T21:18:57",
                                "yyyy-MM-dd'T'HH:mm:ss"));
Enter fullscreen mode Exit fullscreen mode

This will check if the response date is in the range requested!

By the way, this is only one example of how to create a custom result matcher.

Explore the possibilities and create some that suit your needs.

Happy coding!

Follow me on social media, and here on dev.to!

Willian Moya (@WillianFMoya) / X (twitter.com)

Willian Ferreira Moya | LinkedIn

Top comments (0)