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));
}
}
The creativity and intelligence shine through this post on the state of the country. Amazing job!
Learned a lot from this post, and here I was thinking I knew it all. Thanks for the humble pie.
The Writing has become a go-to resource for me. The effort you put into The posts is truly appreciated.
Brilliant writing! You’ve captured the essence perfectly, much like a photographer captures a stunning landscape.
The warmth and intelligence in The writing is as comforting as a cozy blanket on a cold night.
The blend of informative and entertaining content is perfect. I enjoyed every word.
The post was a beacon of knowledge, lighting up my day as if you knew just what I needed to hear.
You have a gift for explaining things in an understandable way, much like a smooth talker who knows just what to say.
You have a gift for explaining things in an understandable way. Thank you!
Charlotte Dog Park’s friendly dogs and owners make it a highlight of our weekly routine.