{"id":89,"date":"2024-01-17T09:27:48","date_gmt":"2024-01-17T12:27:48","guid":{"rendered":"https:\/\/springmasteryhub.com\/?p=89"},"modified":"2024-01-17T09:27:48","modified_gmt":"2024-01-17T12:27:48","slug":"how-to-create-and-use-a-custom-resultmatcher-for-date-testing-with-mockmvc","status":"publish","type":"post","link":"https:\/\/springmasteryhub.com\/?p=89","title":{"rendered":"How to Create and Use a Custom ResultMatcher for Date Testing with MockMvc"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In this tutorial, you will learn how to create a custom ResultMatcher for MockMvc, to suit your project needs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine you are testing an API and the response contains a date. And you want to check if the response date is valid.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Maybe your machine has a different timezone from what\u2019s used in the server.<\/li>\n\n\n\n<li>Maybe some parts of your code can use different time zones.<\/li>\n\n\n\n<li>Maybe your code has a business rule that has to calculate a date and time that can vary in a range.<\/li>\n\n\n\n<li>Maybe you are using LocalDateTime.now() and you cannot mock using the <code>Clock<\/code>.<\/li>\n\n\n\n<li>Or any specific other date manipulation or configuration that your project has.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">When you run your tests you get errors like this, you check for the <code>LocalDateTime.now()<\/code> but the result is a few seconds later.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nExpected: is &quot;2024-01-11T12:37:03.1&quot;\nbut: was &quot;2024-01-11T12:38:21.1&quot;\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Or you have a time zone issue that makes everything 3 hours behind:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nExpected: is &quot;2023-03-07T20:18:57&quot;\nbut: was &quot;2023-03-07T17:18:57&quot;\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to use a custom result matcher to fix this issue?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If we are checking the MockMvc the code should look like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nmvc.perform(get(&quot;\/product\/{}&quot;,productId).contentType(MediaType.APPLICATION_JSON_UTF8))\n                .andExpect(status().isOk())\n                .andExpect(jsonPath(&quot;$.date&quot;, is(&quot;2023-03-07T17:18:57&quot;)));\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">As we said, the problem with this implementation is that the assertion is by the exact date and time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And our time can vary a little bit, so it\u2019ll break our test.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Writing a custom result matcher will enable you to do custom checks as you need.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can write a result matcher that checks if the response date is in a range that you specify.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Example of a custom result matcher for date range validation:<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic static ResultMatcher isDateTimeInRange(String path, String startDateStr, String endDateStr) {\n        LocalDateTime startDate = LocalDateTime.parse(startDateStr, formatter);\n        LocalDateTime endDate = LocalDateTime.parse(endDateStr, formatter);\n        return mvcResult -&gt; {\n            String contentAsString = mvcResult.getResponse().getContentAsString();\n            LocalDateTime checkoutDate = LocalDateTime.parse(JsonPath.read(contentAsString, path), formatter);\n            if (!(checkoutDate.isAfter(startDate) &amp;&amp; checkoutDate.isBefore(endDate))) {\n                throw new AssertionError(String.format(&quot;Date: %s is not between %s and %s&quot;, checkoutDate, startDate, endDate));\n            }\n        };\n    }\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This code allows us to send a start and end range and the date format for the date we\u2019re working.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This will enable us to write our logic to check if the date is in range!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How to use your custom result matcher in your test<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nmvc.perform(get(&quot;\/product\/{}&quot;,productId).contentType(MediaType.APPLICATION_JSON_UTF8))\n                .andExpect(status().isOk())\n                .andExpect(isDateTimeInRange(&quot;$.date&quot;,\n                                &quot;2019-03-07T13:18:57&quot;,\n                                &quot;2019-03-07T21:18:57&quot;,\n                                &quot;yyyy-MM-dd'T'HH:mm:ss&quot;));\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This will check if the response date is in the range requested!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By the way, this is only one example of how to create a custom result matcher.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Explore the possibilities and create some that suit your needs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Happy coding!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Follow me on social media:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/twitter.com\/WillianFMoya\">Willian Moya (@WillianFMoya) \/ X (twitter.com)<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.linkedin.com\/in\/willianmoya\/\">Willian Ferreira Moya | LinkedIn<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":91,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,4,7],"tags":[],"class_list":["post-89","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","category-junit","category-testing"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts\/89","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=89"}],"version-history":[{"count":0,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts\/89\/revisions"}],"wp:attachment":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=89"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=89"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=89"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}