Creating tests for an assignment, I’m getting an strange AssertionError exception.
I have changed it until i got to a simple case:
List<Integer> elements= new ArrayList<Integer>();
elements.add(1);
elements.add(2);
elements.add(3);
Permutation p2 = new Permutation(elements);
Permutation p1 = new Permutation(elements);
assertThat(p2, equalTo(p1));
Permutation.java:
public class Permutation {
private List<Integer> elements;
public Permutation(List<Integer> elements) {
this.elements = elements;
}
public boolean equals(Permutacion permutation){
if ( this.elements.size() != permutation.elements.size()){
return false;
}
Iterator<Integer> iterThis = this.elements.iterator();
Iterator<Integer> iterOther = permutation.elements.iterator();
while ( iterThis.hasNext() && iterOther.hasNext()){
if ( iterThis.next() != iterOther.next()){
return false;
}
}
return true;
}
Digging in both junit and hamcrest source code I have found that junit assertThat only calls matches on the matcher.
The matches method in this case is:
public boolean matches(Object arg) {
return areEqual(arg, object);
}
private static boolean areEqual(Object o1, Object o2) {
if (o1 == null) {
return o2 == null;
} else if (o2 != null && isArray(o1)) {
return isArray(o2) && areArraysEqual(o1, o2);
} else {
return o1.equals(o2);
}
}
Where arg should be “p2” and object should be “p1”.
(It can be browsed at Hamcrest repository)
The results of the comparisons in areEqual method, using debugger inspection, are:
"p2 == null" false
"p1 != null" true
"p2.getClass().isArray()" false
"p2.equals(p1)" true
"equalTo(p1).matches(p2)" false
So as you can see, the code should reach the last else condition and return true ( p2.equals(p1)), but equalTo(p1).matches(p2) returns false
Thanks for your help
Why would you expect
p2.equals(p1)to returntrue? You haven’t overriddenequalsin thePermutationclass, so it will use reference identity by default. You need to overrideequals(andhashCode, in general, to match equals) to indicate what you mean by equality when it comes to permutations.EDIT: Now you’ve posted more code, it’s clearer what’s going on. Your equals method has this signature:
That doesn’t override
Object.equals, which is what the matcher will be using. Instead, it overloads it – introducing a new method, which is what is being called in the debugger inspection. If you write:then
p2.equals(o1)will showfalsein the debugger too – and that’s effectively what the matcher is doing. Your equals method should look something like:(You should also override
hashCodein a way which corresponds to this.)Additionally:
elementsis null, or validate it in the constructor