5
\$\begingroup\$

I needed to check the values in various Lists and Maps. In my case, the various types of Objects that needed checking were of four types:

  1. String
  2. List<String>
  3. Map<String, String>
  4. Map<String, List<String>>

So, I came up with the following types test methods:

@Test
public void testString() {
    Assert.assertEquals("String Mismatch;", providedString, receivedString);
}

@Test
public void testList() {
    Assert.assertNotNull("Provided List is null;", providedList);
    Assert.assertNotNull("Received List is null;", receivedList);
    Assert.assertEquals("Size mismatch for lists;", providedList.size(), receivedList.size());
    Assert.assertTrue("Missing values in received list; Missing: " + CollectionUtils.subtract(providedList, receivedList) + "; ", receivedList.containsAll(providedList));
}

@Test
public void testMap() {
    Assert.assertNotNull("Provided Map is null;", providedMap);
    Assert.assertNotNull("Received Map is null;", receivedMap);
    Assert.assertEquals("Size mismatch for maps;", providedMap.size(), receivedMap.size());
    Assert.assertTrue("Missing keys in received map;", receivedMap.keySet().containsAll(providedMap.keySet()));

    providedMap.keySet().stream().forEach((key) -> {
        Assert.assertEquals("Value mismatch for key '" + key + "';", providedMap.get(key), receivedMap.get(key));
    });
}

@Test
public void testMapList() {
    Assert.assertNotNull("Provided Map is null;", providedMapList);
    Assert.assertNotNull("Received Map is null;", receivedMapList);
    Assert.assertEquals("Size mismatch for maps;", providedMapList.size(), receivedMapList.size());
    Assert.assertTrue("Missing keys in received map;", receivedMapList.keySet().containsAll(providedMapList.keySet()));

    providedMapList.keySet().stream().forEach((key) -> {
        List<String> pList = providedMapList.get(key);
        List<String> rList = receivedMapList.get(key);

        Assert.assertNotNull("Provided List is null for key '" + key + "';", pList);
        Assert.assertNotNull("Received List is null for key '" + key + "';", rList);
        Assert.assertEquals("Size mismatch for lists for key '" + key + "';", pList.size(), rList.size());
        Assert.assertTrue("Missing values in received list for key '" + key + "';", rList.containsAll(pList));
    });
}

The test methods in my project follow the above standard methods depending upon the object that I'm testing for. They are working fine but I'm not completely confident about the coverage.

Also, in the above snippets I've used provided and received as placeholders. In the actual test cases, certain methods are being called to populate the corresponding objects for provided and received. So, they are not necessarily being populated/initialized in @BeforeClass or @Before.

Should I be creating different Test methods for each assert (excluding assertNotNull() methods) that I'm doing? Am I missing any case? Can this be made shorter with the coverage being the same?


Update:

Full Code for testing: Standard Test

Create a TestRunner class to run it and get the results using the following:

Result result = JUnitCore.runClasses(StandardTest.class);
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Map equals has same coverage and it is not attached to implementation: See map.equals javadoc.

So "better" (at least, more compact code) would be:

  assertEquals("something", providedMap, receivedMap);

Well, same for list. That means, you can use the same command as above.

  assertEquals("something", providedList, receivedList);      

And even more...

  assertEquals("something", providedMapList, receivedMapList);

Sure, you will not see which key is missing.

So, you can create new static matchers, as assertEquals that could provide more information. But, assertEquals already prints the content of each container (executing toString of expected and received object), so you can figure out what is missing anyway.

Example:

java.lang.AssertionError: 
Expected :[1, 2, 3, 4, 6]
Actual   :[1, 2, 3, 4, 5]

Edited

If the output is too big, you can use your method. There are some options to follow:

  1. Create a class with static methods (similar with org.junit.Assert)

    public class ContainerAssert {
    
    public static <U, V >void assertEquals(Map<U, V> providedMap, Map<U, V> receivedMap) {
        Assert.assertNotNull("Provided Map is null;", providedMap);
        Assert.assertNotNull("Received Map is null;", receivedMap);
        Assert.assertEquals("Size mismatch for maps;", providedMap.size(), receivedMap.size());
        Assert.assertTrue("Missing keys in received map;", receivedMap.keySet().containsAll(providedMap.keySet()));
    
        providedMap.keySet().stream().forEach((key) -> {
            Assert.assertEquals("Value mismatch for key '" + key + "';", providedMap.get(key), receivedMap.get(key));
        });
      }
      // ...
    }
    
  2. Use Hamcrest

     // with strict order
     List<String> collection = Lists.newArrayList("ab", "cd", "ef");
     assertThat(collection, contains("ab", "cd", "ef"));
    
  3. Use Hamcrest and create a specialized matcher

\$\endgroup\$
2
  • \$\begingroup\$ Yes, it seem to be covering all the cases I thought above. Only thing is that, if instead of String we had a big enough Map/List of objects of some class, then the Expected/Actual output may become too long and complicated. \$\endgroup\$ Jun 27, 2016 at 9:23
  • 1
    \$\begingroup\$ @BileshGanguly, I gave you other options. Hope it can help. \$\endgroup\$
    – rdllopes
    Jun 27, 2016 at 9:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.