Issue
I have a simple pojo class in the format as shown below.
class PojoClass {
property1;
...
propertyN;
@override
public int hashcode() {
//implementation
}
@override
public boolean equals(Object o) {
//implementation
}
@override
public String toString)() {
return "PojoClass[property1= " + property1 ... propertyN + "]";
}
}
In my test case I do what I need and I have an expected PojoClass
object and actual PojoClass
Object. In some cases even arrays (expected and actual) of objects of PojoClass
. When assert
fails, I get message that prints the toString
of expected and actual.
toString
is not convenient enough in this case as my PojoClass
object contains 20 to 30 properties. I am having to manually check all the properties if they match or not. Is there any way in JUnit, to directly specify if which property of expected object did not match that of actual object?
Solution
Solution using Gson
. The basic idea behind this solution is to get the objects values from toString
and de-serialize it into Json
, and then use Maps.difference
method in the Gson
library to compare two Json
s and figure out which property(s)'s or key(s)'s value is a mismatch.
- Update Pojo's to string to return a stringified json of that particular object of POJO
class PojoClass {
property1;
...
propertyN;
@override
public int hashcode() {
//implementation
}
@override
public boolean equals(Object o) {
//implementation
}
@override
public String toString)() {
return new Gson().toJson(this);
}
}
- Test case should look like this, as Hades pointed out.
@Test
public void pojoClassTest() throws Exception {
List<PojoClass> sourcePojoList = getSourcePojoList();
List<PojoClass> targetPojoList = getTargetPojoList();
try {
Assert.assertArrayEquals(sourcePojoList.toArray(), targetPojoList.toArray());
}
catch (ArrayComparisonFailure e) {
Assert.fail(getMessage(e));
}
}
getMessage
method is where we get the existing message fromJUnit
, create twoJson
s and compare them. Refer this post for the comparison technique.
// The junit error message will be in following format
// java.lang.AssertionError: arrays first differed at element [0]; expected:<{json}> but was:<{json}>
// So we get both source and target Json, and throw in the magic of gson library
// We compare them using method mentioned in link above.
// Now the new message that will be asserted contains message like below (assuming property 1 of the object is the mismatch)
// not equal: value differences={property1=("expected","actual")}
private static String getMessage(AssertionError e) throws IOException {
String msg = e.getMessage();
String sourceJson = msg.substring(msg.indexOf("expected:<") + 10, msg.indexOf("> but was:"));
String targetJson = msg.substring(msg.lastIndexOf("but was:<") + 9, msg.lastIndexOf(">"));
Gson g = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> firstMap = g.fromJson(sourceJson, mapType);
Map<String, Object> secondMap = g.fromJson(targetJson, mapType);
return Maps.difference(firstMap, secondMap).toString();
}
Answered By - Arun S R