JUnit Testing a Map of Maps – Map<String, Map<String, Object>>

Let’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.

There are many options for unit testing a Map of Maps, but I’m particularly more fond of the assertThat approach with Matchers. I will always strive to use these over the rudimentary assertEquals, assertTrue and assertFalse, 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 ultimate form of flattery in the newer versions of Java’s JUnit. Below you can find several examples of how to leverage JUnit to test Maps of Maps:

 import org.hamcrest.CoreMatchers;
 import org.hamcrest.collection.IsMapContaining;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.junit.MockitoJUnitRunner;

 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.collection.IsMapContaining.hasEntry;
 
 @RunWith(MockitoJUnitRunner.class)
 public class MapOfMapTest {

     @InjectMocks
     private Processor processor;
     
     @Test
     public void testProcess_CloseIsTrue_ExpectTrue() throws Exception {
         // setup
         ...
         
         // when
         ...
 
         // test
         Map<String, Map<String, Object>> mapOfMaps = (Map<String, Map<String, Object>>) processor.process();
         assertThat(mapOfMaps, is(notNullValue()));

         Map<String, Object> cusipMap = new HashMap<>();
         cusipMap.put("ticker", "BGNIXS");
         String cusip = "091929695";
         cusipMap.put("cusip", cusip);
         cusipMap.put("name", "BlackRock GNMA Instl");
         cusipMap.put("closed", true);
         cusipMap.put("scale", 3);
         Map<String, Object> actual = mapOfMaps.get(cusip);
 
         compareMaps(mapOfMaps, cusipMap, cusip, actual);
     }

     protected void compareMaps(Map<String, Map<String, Object>> mapOfMaps, Map<String, Object> cusipMap, String cusip,
         Map<String, Object> actual) {
         // The most basic pure JUnit assertion, but probably the least preferred option. This is not expressive and will provide poor feedback on failure
         assertTrue(actual.equals(cusipMap));
         
         // 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
         assertEquals(actual, cusipMap);
         
         // Mildly more expressive and would be preferred in my opinion over the above two options
         assertThat(actual, is(cusipMap));
         
         // ----------------------------------------------------------------------------------------------------

         // Using Hamcrest CoreMatchers - more expressive than the above
         assertThat(actual, CoreMatchers.<Map<String, Object>>equalTo(cusipMap));
         
         // Using Hamcrest CoreMatchers - check a specific key and value and is more expressive than the above
         assertThat(mapOfMaps, hasEntry(equalTo(cusip), CoreMatchers.<Map<String, Object>>equalTo(cusipMap)));
         
         // ----------------------------------------------------------------------------------------------------
         
         // Using Hamcrest: Ensure the key used for the outer map is present
         assertThat(mapOfMaps, IsMapContaining.hasKey(cusip));
         
         // Using Hamcrest: Ensure the actual inner Map value is present in the output Map ... this is obvious
         assertThat(mapOfMaps, IsMapContaining.hasValue(actual));
         
         // Using Hamcrest: Ensure the generated inner Map value is present in the output Map ... this is the more valid test
         assertThat(mapOfMaps, IsMapContaining.hasValue(cusipMap));
         
         // Using Hamcrest: Two for one assertion that takes care of checking the key and the value ... use this one
         assertThat(mapOfMaps, IsMapContaining.hasEntry(cusip, cusipMap));
     }
 } 

One Comment:

  1. Needed to draft you one very small remark so as to thank you so much as before relating to the pretty techniques you’ve discussed above. It’s simply surprisingly generous of people like you to grant freely all a few individuals would have offered for sale for an electronic book to earn some profit for themselves, primarily since you might well have done it if you decided. Those creative ideas likewise acted like a great way to realize that other individuals have the same eagerness the same as my own to learn much more in respect of this condition. I’m certain there are thousands of more fun opportunities up front for people who take a look at your website.

Leave a Reply

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