Assertj: How to compare 2 objects list by objects content?
Asked Answered
S

5

12

Given the following (quick and missing) code:

class Pair{
int x;
int y;
}

List l1 = Arrays.asList(new Match(1,2), new Match(1,3), new Match(2,3));
List l2 = Arrays.asList(new Match(1,2), new Match(1,3), new Match(2,3));

How can I compare the content of the lists? Everything I used so far checked if the objects themselves were equal and not the objects value:

assertThat(l1).isEqualTo(l2);
assertThat(l1).containsAll(l2);
assertThat(l1).containsExactly(values);
assertThat(l1).containsExactlyElementsOf(iterable);

Must I implement equals() method for Match class?

May this be the correct way?

for (int i = 0; i < l1.size(); i++){
    assertThat(l1.get(i)).usingRecursiveComparison().isEqualTol2.get(i));
}
Seaside answered 23/10, 2020 at 21:10 Comment(0)
G
16

Give a try to usingRecursiveFieldByFieldElementComparator(recursiveConfiguration), it enables recursive comparison to all iterable assertions.

Ex:

public class Person {
  String name;
  boolean hasPhd;
}

public class Doctor {
  String name;
  boolean hasPhd;
}

Doctor drSheldon = new Doctor("Sheldon Cooper", true);
Doctor drLeonard = new Doctor("Leonard Hofstadter", true);
Doctor drRaj = new Doctor("Raj Koothrappali", true);

Person sheldon = new Person("Sheldon Cooper", false);
Person leonard = new Person("Leonard Hofstadter", false);
Person raj = new Person("Raj Koothrappali", false);
Person howard = new Person("Howard Wolowitz", false);

List<Doctor> doctors = list(drSheldon, drLeonard, drRaj);
List<Person> people = list(sheldon, leonard, raj);

RecursiveComparisonConfiguration configuration = RecursiveComparisonConfiguration.builder()
                                                                                 .withIgnoredFields("hasPhd")
                                                                                 .build();

// assertion succeeds as both lists contains equivalent items in order.
assertThat(doctors).usingRecursiveFieldByFieldElementComparator(configuration)
                   .contains(sheldon);

See https://assertj.github.io/doc/#assertj-core-recursive-comparison-for-iterable for a more detailed explanation.

Grebe answered 25/10, 2020 at 6:12 Comment(3)
When trying this one the compiler is expecting a Doctor object for the contains() method.Pitchblack
Looks like we need to cast the list assertThat((List) doctors).usingRecursiveFieldByFieldElementComparator(configuration) .contains(sheldon);Pitchblack
Found better assertThat(doctors).asList().usingRecursiveFieldByFieldElementComparator(configuration).contains(sheldon); Pitchblack
G
6

You should override equals() and hashCode()

Gutter answered 23/10, 2020 at 21:27 Comment(1)
That's correct. See the javadoc of equals() and hashCode() : docs.oracle.com/javase/6/docs/api/java/lang/Object.htmlFayina
S
2

Yes, so after further researching I would recommend:

for (int i = 0; i < l1.size(); i++){
    assertThat(l1.get(i)).usingRecursiveComparison().isEqualTol2.get(i));
}

You can read the details:

https://assertj.github.io/doc/#assertj-core-recursive-comparison

Seaside answered 24/10, 2020 at 14:40 Comment(0)
C
1

Using AssertJ:

assertThat(actualModel)
                    .usingRecursiveComparison()
                    ...variousOtherOptions()
                    .isEqualTo(expectedModel);

Ceruse answered 11/11, 2021 at 1:44 Comment(0)
F
0

@vincentdep is correct. If you are using Java 14 or above, you can use a record class:

public record Pair(int x, int y){};

List l1 = Arrays.asList(new Pair(1,2), new Pair(1,3), new Pair(2,3));
List l2 = Arrays.asList(new Pair(1,2), new Pair(1,3), new Pair(2,3));

assertThat(l1).isEqualTo(l2);
assertThat(l1).containsAll(l2);
Fayina answered 23/10, 2020 at 21:30 Comment(2)
Thanks! I am using Java 11.Seaside
I suggest trying the latest versions, it's fun! If you cannot, you have to override equals and hashCode or use a library to do it for you. Project Lombok would generate them while Apache Commons provides methods you can call.Fayina

© 2022 - 2024 — McMap. All rights reserved.