stack man stack man - 14 days ago 6
Java Question

How to reduce code for multiple JUnit assertions?

I've got a massive (300 lines) test method that is formed by assertEquals, i.e:

assertEquals(tmParamResult.get(TagmanConstants.COUNTRY), COUNTRY_UK);
assertEquals(tmParamResult.get(TagmanConstants.STATE), EMPTY_STRING);
assertEquals(tmParamResult.get(TagmanConstants.LOYALTY_CARD), String.valueOf(false));
assertEquals(tmParamResult.get(TagmanConstants.REGISTERED), String.valueOf(false));
assertEquals(tmParamResult.get(TagmanConstants.REG_USER_ID), EMPTY_STRING);
assertEquals(tmParamResult.get(TagmanConstants.REG_DATE), EMPTY_STRING);
assertEquals(tmParamResult.get(TagmanConstants.REG_DAY), EMPTY_STRING);
assertEquals(tmParamResult.get(TagmanConstants.REG_MONTH), EMPTY_STRING);
assertEquals(tmParamResult.get(TagmanConstants.REG_YEAR), EMPTY_STRING);
assertEquals(tmParamResult.get(TagmanConstants.SMS_SERVICE), String.valueOf(false));
assertEquals(tmParamResult.get(TagmanConstants.IS_INT), String.valueOf(false));


is there any way to refactor this? (Reflection, maybe?)

Thanks in advance.

Answer

If you model has many fields to check, indeed, you have not the choice you should check each field value.

Now, the way you handle that is maybe not the most suitable solution since if you want to do equals assertion with a tmParamResult instance for another test case, you should rewrite all Assert.assert(...) for each field.
You could create a private method which takes as parameter the expected and the actual tmParamResult. In this way, for each scenario, you only need to create another expected instance with probably some predefined values for some scenarios.

tmParamResult is probably a Map but I prefer not guessing.

@Test
public void assertTmParamResultEquals(TmParamResult tmParamResultActual,TmParamResult tmParamResultExpected){
  assertEquals( 
  tmParamResultExpected.get(TagmanConstants.COUNTRY),
  tmParamResultActual.get(TagmanConstants.COUNTRY)
  ....
 )

UPDATE If you use Map object, you could use unitils library to perform assertion based on reflection. Here you could find more information : http://www.unitils.org/tutorial-reflectionassert.html

Maven dependency :

<dependency>
    <groupId>org.unitils</groupId>
    <artifactId>unitils-test</artifactId>
    <version>3.4.3</version>
</dependency>

It allows to perform reflection assertion even on map.

Here is a simple example :

@Test
public void assertMap() throws Exception {
  Map<String, String> expectedMap = new HashMap<String, String>();
  expectedMap.put("a", "1");
  expectedMap.put("b", "2");

  Map<String, String> actualMap = new HashMap<String, String>();
  actualMap.put("b", "2");
  actualMap.put("a", "1");

  ReflectionAssert.assertReflectionEquals(expectedMap, actualMap, ReflectionComparatorMode.LENIENT_ORDER);

}

With the first proposition, you could give do the assertion in this way :

@Test
public void assertTmParamResultEquals(TmParamResult tmParamResultActual,TmParamResult tmParamResultExpected){
  ReflectionAssert.assertReflectionEquals(tmParamResultExpected, tmParamResultActual, ReflectionComparatorMode.LENIENT_ORDER);
 )