junit4 icon indicating copy to clipboard operation
junit4 copied to clipboard

`failNotSame` message could emphasize reference equality

Open sabi0 opened this issue 6 years ago • 3 comments

When calling assertSame for two different instances of identical objects the failure message will be quite confusing: "expected same:<[1, 2]> was not:<[1, 2]>". See https://github.com/junit-team/junit4/blob/8c9e81daf38efa8b4af9ba5c55fe83765ac434d6/src/main/java/org/junit/Assert.java#L829

I think the clarity could be improved by adding identityHashCode to the message, like this: "expected same:<[1, 2]@ba38e> was not:<[1, 2]@de440>" Or maybe even with the class name: "expected same:<java.util.List@ba38e [1, 2]> was not:<java.util.List@de440 [1, 2]>"

sabi0 avatar Sep 05 '19 20:09 sabi0

There are cases when identityHashCode is not needed, like enum or when it's already present in toString(), like default implementation in Object. It should not be added always for sure, a good question if it's worth determining cases like Collection or leave the implementation as is.

panchenko avatar Sep 06 '19 05:09 panchenko

Well, technically enum values could also produce identical toString() output. And though one wouldn't normally do that such assumption can not be made JUnit code.

Instead of targeting specific cases why not just address the essence of the issue - identical toString() outputs? How about this?

String expectedString = String.valueOf(expected);
String actualString = String.valueOf(actual);
if (expectedString.equals(actualString)) {
    if (expected != null) {
        expectedString = expected.getClass().getName() + '@' + System.identityHashCode(expected) + ' ' + expectedString;
    }
    if (actual != null) {
        actualString = actual.getClass().getName() + '@' + System.identityHashCode(actual) + ' ' + actualString;
    }
}
fail(formatted + "expected same:<" + expectedString + "> was not:<" + actualString + '>');

Then even cases like assertSame(null, "null") would produce a clear output:

expected same:< null> was not:<java.lang.String@de440 null>

sabi0 avatar Sep 06 '19 06:09 sabi0

@sabi0 FWIW JUnit Jupiter includes the identity hash code if both strings are equal. https://github.com/junit-team/junit5/blob/b7897dbf9c70158f3fee76c56b9c1508b416968c/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java#L115-L129

marcphilipp avatar Sep 10 '19 18:09 marcphilipp