Assert.assertEquals junit parameters order


The order of the parameters for Assert.assertEquals method in JUnit is (expected, actual)

Although in another thread someone said that is for no reason, in one of my Java classes in Uni the professor mentioned a specific reason of that ordering, but I don't remember it.

Anybody can help me out with this?

Best Solution

  1. Proper labeling in tools/failure results - The tools are following this order and some GUI tools will label which value is the expected value and which value is the actual value. At the very least, it will minimize confusion if the labels match the values; at worst, you spend time/effort tracking down the wrong issue trying to trace the source of the actual value that wasn't actually the actual value.

  2. Consistency across assertEquals usage - If you aren't consistent in your order throughout your assertions, you can confuse future-you (or other future maintainer) if the values are swapped arbitrarily from case-to-case, again lending to potential confusion.

  3. Consistent parameter ordering across assert methods - It may be reversible for assertEquals, but the order may matter for other assert* methods (in JUnit's built-ins and in other supporting code/libs). Better to be consistent across them all.

  4. Changes in future - Finally, there may be a difference in a future implementation.

  5. *Technical* - Its the expected value's equals method that is used:

There's one subtle difference after looking at the code. Many of the uses of assertEquals() will end up running through this method:

115 static public void assertEquals(String message, Object expected,
116         Object actual) {
117     if (expected == null && actual == null)
118         return;
119     if (expected != null && isEquals(expected, actual))
120         return;
129 private static boolean isEquals(Object expected, Object actual) {
130     return expected.equals(actual);
131 }

Its the equals method of the expected value that is used when both objects are non-null. One could argue that you know the class of the expected value (and thus know the behavior of the equals method of the expected value's class) but you may not necessarily know for certain the class of the actual value (which in theory could have a more permissive equals method). Therefore, you could get a different result if you swap the two arguments (i.e. the two different classes' equals methods are not reflexive of each other):

A contrived case would be an expected value of an ArrayList and an actual value that could return any type of Collection instance, possibly an ArrayList, but also possibly an instance of a custom Collection non-List class 'Foo' (i.e. Foo does not implement List). The ArrayList's equals method (actually its AbstractList.equals) specifies:

Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal.

Perhaps 'Foo' class's equals method is more permissive specifying:

Returns true if and only if the specified object is also a collection, both collections have the same size, and both collections contain equal objects but not necessarily in the same order.

By saying:

ArrayList expectArrayList = ...;
Collection actualCollectionPossiblyFoo = ...
Assert.assertEquals(expectedArrayList, actualCollectionPossiblyFoo)

you are saying you expect something equivalent to an ArrayList (according to ArrayList/AbstractList's definition of equals). This will fail if actualCollectionPossiblyFoo is really of class Foo and thus not a List as required by the ArrayList equals method.

However, this isn't the same as saying:

ArrayList expectedArrayList = ...;
Collection actualCollectionPossiblyFoo = ...;
Assert.assertEquals(actualCollectionPossiblyFoo, expectedArrayList);

because actualCollectionPossbilyFoo may be an instance of Foo and Foo may consider itself and expectedArrayList to be equal according to Foo class's equals method.