-
-
Notifications
You must be signed in to change notification settings - Fork 749
Closed
Milestone
Description
equals
and hashCode
are used in the implementation of satisfiesExactlyInAnyOrder
(when they definitely aren't needed). This can result in incorrect assertion results.
- assertj core version: 3.25.1
- java version: 17
- test framework version: n/a
- os (if relevant):
Example of the issue:
public class MyTest {
@Test
void shouldPassButFails() {
StringAndInt first = new StringAndInt("X", 1);
StringAndInt second = new StringAndInt("X", 2);
assertThat(List.of(first, second)).satisfiesExactlyInAnyOrder(
stringAndInt -> assertThat(stringAndInt.integer).isEqualTo(2),
stringAndInt -> assertThat(stringAndInt.integer).isEqualTo(1)
);
}
private static final class StringAndInt {
private final String string;
private final int integer;
private StringAndInt(
String string,
int integer
) {
this.string = string;
this.integer = integer;
}
@Override
public int hashCode() {
return string.hashCode();
}
@Override
public boolean equals(Object o) {
return (o instanceof StringAndInt other) && other.string.equals(string);
}
@Override
public String toString() {
return "StringAndInt{" +
"string='" + string + '\'' +
", integer=" + integer +
'}';
}
}
}
This test fails with
Expecting actual:
[StringAndInt{string='X', integer=1}, StringAndInt{string='X', integer=2}]
to satisfy all the consumers in any order.
but should pass.
The problem is that the use of List::remove
in the implementation results in the wrong element being removed.
In general we believe there are a number of bugs in assertj due to unnecessary usages of equals
and hashCode
, and think that the best way to weed them out is to have unit tests using classes where equals
and hashCode
throw exceptions.
davidboden and joel-costigliola