Gangnus
Gangnus

Reputation: 24484

Strange behaviour of Assert.assertEquals

According to many posts here, Assert.assertEquals should compare collections using deep insight, and two arrays of the same content should be equal.

I have JUnit 4.12 installed.

Calling

List<Integer[]> result, targetResult;
(both are created as ArrayList)
....
Assert.assertEquals("counted small array ", result, targetResult);

, where result and targetResult have the same content, the test fails though.

I have looked how the assertEquals do the job. For comparison of the Integer arrays it reached:

//----in AbstractList: 
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof List))
        return false;

    ListIterator<E> e1 = listIterator();
    ListIterator e2 = ((List) o).listIterator();
    while (e1.hasNext() && e2.hasNext()) {
        E o1 = e1.next();
        Object o2 = e2.next();
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    ...

//and more deep, in Object:
public boolean equals(Object obj) {
    return (this == obj);
}

And that means, that it compares simply references.

How can I make Assert.assertEquals() to work correctly?

Upvotes: 1

Views: 755

Answers (2)

Peter Lawrey
Peter Lawrey

Reputation: 533870

The problem with assertEquals is the assumption that the equals(Object) is sane. Unfortunately, all arrays inherent from Object directly and have no specialised methods. This means that you have to call Arrays.equals(a, b) to compare two arrays, however if those arrays are inside a collection there is no way to do this conveniently.

Note: I don't know why printing [Ljava.lang.Integer@72173fed is a good toString for such an array either (it is something I have ranted against in my blog more than once)

And that means, that it compares simply hashcodes.

It doesn't compare hashCode()s, it compares references. hashCode()s are not memory addresses, nor can they be as they cannot change when the object is moved in memory.

If you want your data structures to be equal, use a collection which supports equals as you expect

List<List<Integer>> result

if you you want efficiency as int use 4 bytes and Integer can use 20 bytes including it's reference.

List<int[]> result

public static void assertEqualsArray(List<Int[]> a, List<int[]> b) {
   // compare the list of arrays.
}

Upvotes: 4

Anonymous
Anonymous

Reputation: 86379

Consider:

Assert.assertArrayEquals(result.toArray(), targetResult.toArray());

Upvotes: 0

Related Questions