Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursive comparison uses equals on root object when useOverriddenEquals is enabled #3320

Closed
austinarbor-wk opened this issue Jan 2, 2024 · 13 comments
Assignees
Labels
theme: recursive comparison An issue related to the recursive comparison type: regression A regression from a previous release
Milestone

Comments

@austinarbor-wk
Copy link

austinarbor-wk commented Jan 2, 2024

Describe the bug
It appears that 3.25.0 has changed behavior of recursive comparison

  • assertj core version: 3.25.0
  • java version: 17
  • test framework version: junit platform 5.10.1

The below test succeeds in 3.24.2 but fails in 3.25.0

  @Test
  void testRecursiveCompare() {
    var a1 = new A();
    a1.name = "test1";
    var b1 = new B();
    a1.b = b1;
    b1.name = "test2";

    var a2 = new A();
    a2.name = "test1";
    a2.b = b1;

    var list1 = List.of(a1);
    var list2 = List.of(a2);

    var cfg = RecursiveComparisonConfiguration.builder().withComparedFields("name", "b").build();
    cfg.useOverriddenEquals();

    assertThat(list1)
        .usingRecursiveFieldByFieldElementComparator(cfg)
        .containsExactlyElementsOf(list2);
  }

  private static class A {
    private String name;

    private String guid = UUID.randomUUID().toString();

    private B b;

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof A a)) {
        return false;
      }
      return Objects.equals(name, a.name) && Objects.equals(guid, a.guid) && Objects.equals(b, a.b);
    }

    @Override
    public int hashCode() {
      return Objects.hash(name, guid, b);
    }
  }

  private static class B {
    private String name;

    private String guid = UUID.randomUUID().toString();

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof B b)) {
        return false;
      }
      return Objects.equals(name, b.name) && Objects.equals(guid, b.guid);
    }
  }
@scordio scordio added theme: recursive comparison An issue related to the recursive comparison type: regression A regression from a previous release labels Jan 2, 2024
@scordio
Copy link
Member

scordio commented Jan 2, 2024

Thanks for reporting it, @austinarbor-wk!

@scordio scordio added this to the 3.25.2 milestone Jan 2, 2024
@scordio
Copy link
Member

scordio commented Jan 7, 2024

Possibly related to 0eb44cc and still unsure if the behavior in version 3.24.2 was correct, though.

What should be the expected behavior when withComparedFields("name", "b") and useOverriddenEquals() are used together, and the overridden equals compares also guid?

I feel useOverriddenEquals() should win on top of any withComparedFields(...) config, like the behavior of 3.25. Maybe we should prevent such config combinations or fail fast with some IllegalStateException.

Any thoughts @joel-costigliola?

@austinarbor-wk
Copy link
Author

I think my expectation from the original code sample above based on the javadoc is that the comparison would be equivalent to the compound assertion of

assertThat(a1.name).isEqualTo(a2.name)
assertThat(a1.b).isEqualTo(a2.b)

Is my understanding incorrect?

@scordio
Copy link
Member

scordio commented Jan 8, 2024

Do I understand correctly that you'd like to use the overridden equals only for B but not for A?

@joel-costigliola
Copy link
Member

I would expect both compared fields to be compared with equals, compared fields limits the comparison to the specified fields and useOverriddenEquals() instructs the recursive comparison to compare them with their equals method.

I'll have a look at the issue this week.

@joel-costigliola joel-costigliola self-assigned this Jan 8, 2024
@austinarbor-wk
Copy link
Author

My expectation is how @joel-costigliola describes

@joel-costigliola
Copy link
Member

Alright, the issue is that the code that decides whether to use the overridden equals or not does not honor the compared fields, in the given example test it decides to compare A and B with equals instead of only comparing the name and b fields

@joel-costigliola joel-costigliola added the type: bug A general bug label Jan 9, 2024
@scordio scordio changed the title Regression in Recursive Comparison Recursive comparison uses equals on root object when useOverriddenEquals is enabled Jan 18, 2024
@scordio scordio removed the type: bug A general bug label Jan 18, 2024
@schlosna
Copy link
Contributor

Thank you for the assertj project, it makes reading & writing tests enjoyable.

I am curious if there is a timeline for 3.25.2 release with the fix for this issue. We have had to roll back a number of projects to 3.24.2 due to tests using recursive comparison timing out and failing.

Thank you!

@scordio
Copy link
Member

scordio commented Jan 19, 2024

@schlosna yes, we plan to release 3.25.2 later this month, as soon as we finish looking into its remaining issues.

@schlosna
Copy link
Contributor

Thank you for the 3.25.2 release! I ran some quick tests using 3.25.2 and it has resolved the issues we were encountering with usingRecursiveComparison.

@austinarbor-wk
Copy link
Author

Confirmed 3.25.2 resolves the issues we were experiencing as well, thanks!

@joel-costigliola
Copy link
Member

Thanks for the feedback, appreciated!

@ash211
Copy link
Contributor

ash211 commented Jan 26, 2024

@schlosna and I work together -- 3.25.2 solves most of the recursive comparison issues we had, but not all. I've identified a regression in comparing deeply-nested objects and opened a demonstrative test case at #3350.

Thoughts on that PR would be much appreciated! Thanks again for assertj.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme: recursive comparison An issue related to the recursive comparison type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

5 participants