{"id":614,"date":"2021-03-11T03:04:11","date_gmt":"2021-03-11T03:04:11","guid":{"rendered":"http:\/\/kevinmichaelcoy.com\/blog\/?p=614"},"modified":"2021-03-11T18:02:56","modified_gmt":"2021-03-11T18:02:56","slug":"unit-testing-a-map-of-map-map","status":"publish","type":"post","link":"http:\/\/kevinmichaelcoy.com\/blog\/2021\/03\/11\/unit-testing-a-map-of-map-map\/","title":{"rendered":"JUnit Testing a Map of Maps &#8211; Map&lt;String, Map&lt;String, Object&gt;&gt;"},"content":{"rendered":"\n<p>Let&#8217;s say you encounter a situation where you have a Map of Maps where the nested Map has a value of Object. These were the cards I was dealt while refactoring a bit of code recently. This case may be a bit too generic and likely warrants a more specific domain object at the least; however, I maintained this structure to remain backward compatible I did some TDD to make sure nothing was broken by the refactoring.<\/p>\n\n\n\n<p>There are many options for unit testing a Map of Maps, but I&#8217;m particularly more fond of the <code>assertThat<\/code> approach with Matchers. I will always strive to use these over the rudimentary <code>assertEquals<\/code>, <code>assertTrue<\/code> and <code>assertFalse<\/code>, which provides little value for reporting and troubleshooting. Hamcrest is one of those open-source libraries in Java that has become so popular that it has basically received the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hamcrest\">ultimate form of flattery in the newer versions of Java&#8217;s JUnit<\/a>. Below you can find several examples of how to leverage JUnit to test Maps of Maps:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\"> import org.hamcrest.CoreMatchers;\n import org.hamcrest.collection.IsMapContaining;\n import org.junit.Before;\n import org.junit.Test;\n import org.junit.runner.RunWith;\n import org.mockito.InjectMocks;\n import org.mockito.Mock;\n import org.mockito.Mockito;\n import org.mockito.junit.MockitoJUnitRunner;\n\n import java.io.IOException;\n import java.util.HashMap;\n import java.util.Map;\n \n import static org.hamcrest.CoreMatchers.equalTo;\n import static org.hamcrest.CoreMatchers.is;\n import static org.hamcrest.CoreMatchers.notNullValue;\n import static org.hamcrest.collection.IsMapContaining.hasEntry;\n \n @RunWith(MockitoJUnitRunner.class)\n public class MapOfMapTest {\n\n &nbsp; &nbsp; @InjectMocks\n &nbsp; &nbsp; private Processor processor;\n &nbsp;&nbsp; &nbsp;\n &nbsp; &nbsp; @Test\n &nbsp; &nbsp; public void testProcess_CloseIsTrue_ExpectTrue() throws Exception {\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ setup\n &nbsp; &nbsp; &nbsp; &nbsp; ...\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ when\n &nbsp; &nbsp; &nbsp; &nbsp; ...\n \n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ test\n &nbsp; &nbsp; &nbsp; &nbsp; Map&lt;String, Map&lt;String, Object&gt;&gt; mapOfMaps = (Map&lt;String, Map&lt;String, Object&gt;&gt;) processor.process();\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(mapOfMaps, is(notNullValue()));\n\n &nbsp; &nbsp; &nbsp; &nbsp; Map&lt;String, Object&gt; cusipMap = new HashMap&lt;&gt;();\n &nbsp; &nbsp; &nbsp; &nbsp; cusipMap.put(\"ticker\", \"BGNIXS\");\n &nbsp; &nbsp; &nbsp; &nbsp; String cusip = \"091929695\";\n &nbsp; &nbsp; &nbsp; &nbsp; cusipMap.put(\"cusip\", cusip);\n &nbsp; &nbsp; &nbsp; &nbsp; cusipMap.put(\"name\", \"BlackRock GNMA Instl\");\n &nbsp; &nbsp; &nbsp; &nbsp; cusipMap.put(\"closed\", true);\n &nbsp; &nbsp; &nbsp; &nbsp; cusipMap.put(\"scale\", 3);\n &nbsp; &nbsp; &nbsp; &nbsp; Map&lt;String, Object&gt; actual = mapOfMaps.get(cusip);\n \n &nbsp; &nbsp; &nbsp; &nbsp; compareMaps(mapOfMaps, cusipMap, cusip, actual);\n &nbsp; &nbsp; }\n\n &nbsp; &nbsp; protected void compareMaps(Map&lt;String, Map&lt;String, Object&gt;&gt; mapOfMaps, Map&lt;String, Object&gt; cusipMap, String cusip,\n &nbsp; &nbsp; &nbsp; &nbsp; Map&lt;String, Object&gt; actual) {\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ The most basic pure JUnit assertion, but probably the least preferred option. This is not expressive and will provide poor feedback on failure\n &nbsp; &nbsp; &nbsp; &nbsp; assertTrue(actual.equals(cusipMap));\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ The second most basic pure JUnit assertion, and only marginally better than the above. This is not expressive and will provide poor feedback on failure\n &nbsp; &nbsp; &nbsp; &nbsp; assertEquals(actual, cusipMap);\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Mildly more expressive and would be preferred in my opinion over the above two options\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(actual, is(cusipMap));\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ ----------------------------------------------------------------------------------------------------\n\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Using Hamcrest CoreMatchers - more expressive than the above\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(actual, CoreMatchers.&lt;Map&lt;String, Object&gt;&gt;equalTo(cusipMap));\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Using Hamcrest CoreMatchers - check a specific key and value and is more expressive than the above\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(mapOfMaps, hasEntry(equalTo(cusip), CoreMatchers.&lt;Map&lt;String, Object&gt;&gt;equalTo(cusipMap)));\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ ----------------------------------------------------------------------------------------------------\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Using Hamcrest: Ensure the key used for the outer map is present\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(mapOfMaps, IsMapContaining.hasKey(cusip));\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Using Hamcrest: Ensure the actual inner Map value is present in the output Map ... this is obvious\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(mapOfMaps, IsMapContaining.hasValue(actual));\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Using Hamcrest: Ensure the generated inner Map value is present in the output Map ... this is the more valid test\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(mapOfMaps, IsMapContaining.hasValue(cusipMap));\n &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\n &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Using Hamcrest: Two for one assertion that takes care of checking the key and the value ... use this one\n &nbsp; &nbsp; &nbsp; &nbsp; assertThat(mapOfMaps, IsMapContaining.hasEntry(cusip, cusipMap));\n &nbsp; &nbsp; }\n } <\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s say you encounter a situation where you have a Map of Maps where the nested Map has a value of Object. These were the cards I was dealt while refactoring a bit of code recently. This case may be a bit too generic and likely warrants a more specific&#8230;<\/p>\n<p class=\"continue-reading-button\"> <a class=\"continue-reading-link\" href=\"http:\/\/kevinmichaelcoy.com\/blog\/2021\/03\/11\/unit-testing-a-map-of-map-map\/\">Continue reading<i class=\"crycon-right-dir\"><\/i><\/a><\/p>\n","protected":false},"author":2,"featured_media":623,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5,3],"tags":[424,352,423,360,425],"_links":{"self":[{"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/posts\/614"}],"collection":[{"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/comments?post=614"}],"version-history":[{"count":6,"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/posts\/614\/revisions"}],"predecessor-version":[{"id":622,"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/posts\/614\/revisions\/622"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/media\/623"}],"wp:attachment":[{"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/media?parent=614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/categories?post=614"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/kevinmichaelcoy.com\/blog\/wp-json\/wp\/v2\/tags?post=614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}