Home > Software design >  Junit Assertion Error - Getting error even though Expected and actual output are exactly same
Junit Assertion Error - Getting error even though Expected and actual output are exactly same

Time:09-26

I am getting the following error even if the expected and actual output is exactly similar.

org.opentest4j.AssertionFailedError: expected: java.util.ArrayList@2bbf180e<[[1, 2, 3], [4, 5, 6]]> but was: java.util.ArrayList@163e4e87<[[1, 2, 3], [4, 5, 6]]>
at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
at org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1141)
at parseCsvTest$ExampleTests.shouldHandleSimpleInputs(parseCsvTest.java:17)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)

Test cases were written by someone else as I am doing an online assessment on a website so I am not sure how the tests are written.

Here is my code.

public class Challenge {
public static ArrayList<ArrayList<String>> parseCsv(
    String csv,
    String separator,
    String quote
) {
    
    String[] splitted = csv.split("\n");
    ArrayList<ArrayList<String>> result = new ArrayList<>();

    for (int i = 0; i< splitted.length; i  ) {

      String[] st = splitted[i].split(separator);

      String string = new String();
      for (int j = 0; j < st.length; j  ) {
        string  = st[j];
        if (j != st.length - 1) {
          string  = ", ";
        }
     }

     ArrayList<String> temp = new ArrayList<>();
     temp.add(string);
     result.add(temp);
    }
  
  return result;
}

}

CodePudding user response:

Objects ArrayList@2bbf180e and ArrayList@163e4e87 are not equals hence the error.

You can use JUnit 5 Assertions.assertIterableEquals it asserts that expected and actual iterables are deeply equal.

https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Assertions.html#assertIterableEquals(java.lang.Iterable,java.lang.Iterable)

CodePudding user response:

List explicitly states that a List.equals implementation must return true if the argument is also a List, and the two lists have equal elements in the same order. That means that, despite what Issam El-atif said, you should be able to use Assertions.assertEquals. assertIterableEquals is indeed necessary when trying to compare two collections of different types, e.g. a List and a Set.

In your case, the equality check fails. However, the two lists have the same toString() result. That's why you see java.util.ArrayList@2bbf180e<[[1, 2, 3], [4, 5, 6]]> and not just [[1, 2, 3], [4, 5, 6]]. The type and (identity?) hash codes are only added to the message if the unequal objects have the same toString() result, to avoid useless messages like expected: [[1, 2, 3], [4, 5, 6]] but was: [[1, 2, 3], [4, 5, 6]].

The real question now is - what's in the lists? Is one a List<List<Integer>> and the other a List<List<Long>>, a List<List<String>> or something like that? Are the elements of the lists even lists? In other words - does the expected list have the correct objects in it?

Edit: Issam is right if the list elements are collections of different types. assertIterableEquals calls itself if elements are both iterables. However, it will still fail when trying to compare a List<List<Integer>> with a List<List<Long>>. It will succeed when trying to compare a List<List<Integer>> with a List<Set<Integer>> if the nested lists and sets have the same order.

  • Related