Skip to content

satisfiesExactlyInAnyOrder fails if actual overrides equals #3339

@PBoddington

Description

@PBoddington

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions