Class RecursiveComparisonAssert<SELF extends RecursiveComparisonAssert<SELF>>

    • Method Detail

      • isEqualTo

        public SELF isEqualTo​(Object expected)
        Asserts that the object under test (actual) is equal to the given object when compared field by field recursively (including inherited fields are included in the comparison). If the comparison fails it will report all the differences found and which effective RecursiveComparisonConfiguration was used to help users understand the failure.

        This is typically useful when actual's equals was not overridden.

        The comparison is not symmetrical since it is limited to actual's fields, the algorithm gather all actual's fields and then compare them to the corresponding expected's fields.
        It is then possible for the expected object to have more fields than actual which is handy when comparing a base type to a subtype.

        Strict/lenient recursive comparison

        By default the objects to compare can be of different types but must have the same properties/fields. For example if object under test has a work field of type Address, the expected object to compare the object under test to must also have one but it can of a different type like AddressDto.

        It is possible to enforce strict type checking by calling withStrictTypeChecking() and make the comparison fail whenever the compared objects or their fields are not compatible.
        Compatible means that the expected object/field types are the same or a subtype of actual/field types, for example if actual is an Animal and expected a Dog, they will be compared field by field in strict type checking mode.

        Ignoring null fields in the recursive comparison

        When an object is partially populated, it can still be interesting to see if its populated values are correct against a fully populated object.

        This possible by calling ignoringActualNullFields() before isEqualTo but bear in mind that only actual null fields are ignored, said otherwise the expected object null fields are used in the comparison.

        Recursive comparison use of overridden equals methods

        By default the recursive comparison is not applied on fields whose classes have overridden the equals method, concretely it means equals is used to compare these fields instead of keeping on applying the recursive comparison. The rationale is that if a class has redefined equals then it should be used to compare instances unless having a good reason.

        It is possible though to change this behavior and force recursive comparison by calling any of these methods (but before calling isEqualTo otherwise this has no effect!):

        1. ignoringOverriddenEqualsForTypes(Class...) Any fields of these classes are compared recursively
        2. ignoringOverriddenEqualsForFields(String...) Any given fields are compared recursively
        3. ignoringOverriddenEqualsForFieldsMatchingRegexes(String...) Any fields matching one of these regexes are compared recursively
        4. ignoringAllOverriddenEquals() except for java types, all fields are compared field by field recursively.
        Recursive comparison and cycles

        The recursive comparison handles cycles.

        Comparator used in the recursive comparison

        By default floats are compared with a precision of 1.0E-6 and doubles with 1.0E-15.

        You can specify a custom comparator or equals BiPredicate per (nested) fields or type with the methods below (but before calling isEqualTo otherwise this has no effect!):

        1. withEqualsForType(BiPredicate, Class) for a given type
        2. withEqualsForFields(BiPredicate, String...) for one or multiple fields
        3. withComparatorForType(Comparator, Class) for a given type
        4. withComparatorForFields(Comparator, String...) for one or multiple fields

        Note that field comparators always take precedence over type comparators.

        Example

        Here is a basic example with a default RecursiveComparisonConfiguration, you can find other examples for each of the method changing the recursive comparison behavior like ignoringFields(String...).

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
           Date ownedSince;
         }
        
         public static class Address {
           int number;
           String street;
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.ownedSince = new Date(123);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person sherlock2 = new Person("Sherlock", 1.80);
         sherlock2.home.ownedSince = new Date(123);
         sherlock2.home.address.street = "Baker Street";
         sherlock2.home.address.number = 221;
        
         // assertion succeeds as the data of both objects are the same.
         assertThat(sherlock).usingRecursiveComparison()
                             .isEqualTo(sherlock2);
        Specified by:
        isEqualTo in interface Assert<SELF extends RecursiveComparisonAssert<SELF>,​Object>
        Overrides:
        isEqualTo in class AbstractAssert<SELF extends RecursiveComparisonAssert<SELF>,​Object>
        Parameters:
        expected - the object to compare actual to.
        Returns:
        this assertion object.
        Throws:
        AssertionError - if the actual object is null.
        AssertionError - if the actual and the given objects are not deeply equal property/field by property/field.
        IntrospectionError - if one property/field to compare can not be found.
      • isNotEqualTo

        public SELF isNotEqualTo​(Object other)
        Asserts that actual object is not equal to the given object based on a recursive property/field by property/field comparison (including inherited ones).

        This is typically useful when actual's equals was not overridden.

        The comparison is not symmetrical since it is limited to actual's fields, the algorithm gather all actual's fields and then compare them to the corresponding expected's fields.
        It is then possible for the expected object to have more fields than actual which is handy when comparing a base type to a subtype.

        This method is based on isEqualTo(Object), you can check out more usages in that method.

        Example

         // equals not overridden in TolkienCharacter
         TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);
         TolkienCharacter frodoClone = new TolkienCharacter("Frodo", 33, HOBBIT);
         TolkienCharacter youngFrodo = new TolkienCharacter("Frodo", 22, HOBBIT);
        
         // Pass as equals compares object references
         assertThat(frodo).isNotEqualTo(frodoClone);
        
         // Fail as frodo and frodoClone are equals when doing a field by field comparison.
         assertThat(frodo).usingRecursiveComparison()
                          .isNotEqualTo(frodoClone);
        
         // Pass as one the age fields differ between frodo and youngFrodo.
         assertThat(frodo).usingRecursiveComparison()
                          .isNotEqualTo(youngFrodo);
        Specified by:
        isNotEqualTo in interface Assert<SELF extends RecursiveComparisonAssert<SELF>,​Object>
        Overrides:
        isNotEqualTo in class AbstractAssert<SELF extends RecursiveComparisonAssert<SELF>,​Object>
        Parameters:
        other - the object to compare actual to.
        Returns:
        this assertions object
        Throws:
        AssertionError - if the actual object and the given objects are both null.
        AssertionError - if the actual and the given objects are equals property/field by property/field recursively.
        Since:
        3.17.0
        See Also:
        isEqualTo(Object)
      • comparingOnlyFields

        public SELF comparingOnlyFields​(String... fieldNamesToCompare)
        Makes the recursive comparison to only compare given actual fields and their subfields (no other fields will be compared).

        Specifying a field will make all its subfields to be compared, for example specifying person will lead to compare person.name, person.address and all other Person fields.
        On the other hand if you specify person.name, person won't be compared but person.name will be.

        The fields are specified by name, not by value, for example you can specify person.name but not "Jack" as "Jack" is not a field value.

        comparingOnlyFields can be combined with ignoring fields methods to restrict further the fields actually compared, the resulting compared fields = {specified compared fields} - {specified ignored fields}.
        For example if the specified compared fields = {"foo", "bar", "baz"} and the ignored fields = {"bar"} then only {"foo", "baz"} fields will be compared.

        Usage example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person moriarty = new Person("Moriarty", 1.80);
         moriarty.home.address.street = "Butcher Street";
         moriarty.home.address.number = 221;
        
        
         // assertion succeeds as name and home.address.street fields are not compared.
         assertThat(sherlock).usingRecursiveComparison()
                             .comparingOnlyFields("height", "home.address.number")
                             .isEqualTo(moriarty);
        
         // assertion fails as home.address.street fields differ.
         assertThat(sherlock).usingRecursiveComparison()
                             .comparingOnlyFields("height", "home")
                             .isEqualTo(moriarty);
        Parameters:
        fieldNamesToCompare - the fields of the object under test to compare in the comparison.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringActualNullFields

        public SELF ignoringActualNullFields()
        Makes the recursive comparison to ignore all actual null fields (but note that the expected object null fields are used in the comparison).

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
         }
        
         Person noName = new Person(null, 1.80);
         noName.home.address.street = null;
         noName.home.address.number = 221;
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         // assertion succeeds as name and home.address.street fields are ignored in the comparison
         assertThat(noName).usingRecursiveComparison()
                           .ignoringActualNullFields()
                           .isEqualTo(sherlock);
        
         // assertion fails as name and home.address.street fields are populated for sherlock but not for noName.
         assertThat(sherlock).usingRecursiveComparison()
                             .ignoringActualNullFields()
                             .isEqualTo(noName);
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringActualEmptyOptionalFields

        public SELF ignoringActualEmptyOptionalFields()
        Makes the recursive comparison to ignore all actual empty optional fields (including Optional, OptionalInt, OptionalLong and OptionalDouble), note that the expected object empty optional fields are not ignored, this only applies to actual's fields.

        Example:

         public class Person {
           String name;
           OptionalInt age;
           OptionalLong id;
           OptionalDouble height;
           Home home = new Home();
         }
        
         public class Home {
           String address;
           Optional<String> phone;
         }
        
         Person homerWithoutDetails = new Person("Homer Simpson");
         homerWithoutDetails.home.address.street = "Evergreen Terrace";
         homerWithoutDetails.home.address.number = 742;
         homerWithoutDetails.home.phone = Optional.empty();
         homerWithoutDetails.age = OptionalInt.empty();
         homerWithoutDetails.id = OptionalLong.empty();
         homerWithoutDetails.height = OptionalDouble.empty();
        
         Person homerWithDetails = new Person("Homer Simpson");
         homerWithDetails.home.address.street = "Evergreen Terrace";
         homerWithDetails.home.address.number = 742;
         homerWithDetails.home.phone = Optional.of("(939) 555-0113");
         homerWithDetails.age = OptionalInt.of(39);
         homerWithDetails.id = OptionalLong.of(123456);
         homerWithDetails.height = OptionalDouble.of(1.83);
        
         // assertion succeeds as phone is ignored in the comparison
         assertThat(homerWithoutDetails).usingRecursiveComparison()
                                        .ignoringActualEmptyOptionalFields()
                                        .isEqualTo(homerWithDetails);
        
         // assertion fails as phone, age, id and height are not ignored and are populated for homerWithDetails but not for homerWithoutDetails.
         assertThat(homerWithDetails).usingRecursiveComparison()
                                     .ignoringActualEmptyOptionalFields()
                                     .isEqualTo(homerWithoutDetails);
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringExpectedNullFields

        public SELF ignoringExpectedNullFields()
        Makes the recursive comparison to ignore all expected null fields.

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person noName = new Person(null, 1.80);
         noName.home.address.street = null;
         noName.home.address.number = 221;
        
         // assertion succeeds as name and home.address.street fields are ignored in the comparison
         assertThat(sherlock).usingRecursiveComparison()
                             .ignoringExpectedNullFields()
                             .isEqualTo(noName);
        
         // assertion fails as name and home.address.street fields are populated for sherlock but not for noName.
         assertThat(noName).usingRecursiveComparison()
                           .ignoringExpectedNullFields()
                           .isEqualTo(sherlock);
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringFields

        public SELF ignoringFields​(String... fieldNamesToIgnore)
        Makes the recursive comparison to ignore the given object under test fields. Nested fields can be specified like this: home.address.street.

        The given fieldNamesToIgnore are matched against field names, not field values.

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person noName = new Person(null, 1.80);
         noName.home.address.street = null;
         noName.home.address.number = 221;
        
         // assertion succeeds as name and home.address.street fields are ignored in the comparison
         assertThat(sherlock).usingRecursiveComparison()
                             .ignoringFields("name", "home.address.street")
                             .isEqualTo(noName);
        
         // assertion fails as home.address.street fields differ and is not ignored.
         assertThat(sherlock).usingRecursiveComparison()
                             .ignoringFields("name")
                             .isEqualTo(noName);
        Parameters:
        fieldNamesToIgnore - the field names of the object under test to ignore in the comparison.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringFieldsMatchingRegexes

        public SELF ignoringFieldsMatchingRegexes​(String... regexes)
        Makes the recursive comparison to ignore the object under test fields whose name matche the given regexes.

        Nested fields can be specified by using dots like this: home\.address\.street (\ is used to escape dots since they have a special meaning in regexes).

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person noName = new Person(null, 1.80);
         noName.home.address.street = "Butcher Street";
         noName.home.address.number = 222;
        
         // assertion succeeds as name and all home fields are ignored in the comparison
         assertThat(sherlock).usingRecursiveComparison()
                             .ignoringFieldsMatchingRegexes("n.me", "home.*")
                             .isEqualTo(noName);
        
         // although home fields are ignored, assertion fails as name fields differ.
         assertThat(sherlock).usingRecursiveComparison()
                             .ignoringFieldsMatchingRegexes("home.*")
                             .isEqualTo(noName);
        Parameters:
        regexes - regexes used to ignore fields in the comparison.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringFieldsOfTypes

        public RecursiveComparisonAssert<?> ignoringFieldsOfTypes​(Class<?>... typesToIgnore)
        Makes the recursive comparison to ignore the object under test fields of the given types. The fields are ignored if their types exactly match one of the ignored types, for example if a field is a subtype of an ignored type it is not ignored.

        If some object under test fields are null it is not possible to evaluate their types unless in strictTypeChecking mode, in that case the corresponding expected field's type is evaluated instead but if strictTypeChecking mode is disabled then null fields are not ignored.

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person sherlock2 = new Person("Sherlock", 1.90);
         sherlock2.home.address.street = "Butcher Street";
         sherlock2.home.address.number = 221;
        
         // assertion succeeds as we ignore Address and height
         assertThat(sherlock).usingRecursiveComparison()
                             .ignoringFieldsOfTypes(double.class, Address.class)
                             .isEqualTo(sherlock2);
        
         // now this assertion fails as expected since the home.address.street fields and height differ
         assertThat(sherlock).usingRecursiveComparison()
                             .isEqualTo(sherlock2);
        Parameters:
        typesToIgnore - the types we want to ignore in the object under test fields.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringAllOverriddenEquals

        public SELF ignoringAllOverriddenEquals()
        This method instructs the recursive comparison to compare recursively all fields including the one whose type have overridden equals, except fields with java types (at some point we need to compare something!).

        Since 3.17.0 this is the default behavior for recursive comparisons, to revert to the previous behavior call usingOverriddenEquals().

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
        
           // only compares number, ouch!
           @Override
           public boolean equals(final Object other) {
             if (!(other instanceof Address)) return false;
             Address castOther = (Address) other;
             return Objects.equals(number, castOther.number);
           }
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person sherlock2 = new Person("Sherlock", 1.80);
         sherlock2.home.address.street = "Butcher Street";
         sherlock2.home.address.number = 221;
        
         // Assertion succeeds because:
         // - overridden equals are used
         // - Address has overridden equals and does not compare street fields.
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .isEqualTo(sherlock2);
        
         // To avoid using Address overridden equals, don't call usingOverriddenEquals() or call ignoringAllOverriddenEquals()
         // (calling ignoringAllOverriddenEquals() is actually not required as this is the default behavior).
         // This assertion fails as it will compare home.address.street fields which differ
         assertThat(sherlock).usingRecursiveComparison()
                              //.ignoringAllOverriddenEquals() // not needed as this is the default
                             .isEqualTo(sherlock2);
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • usingOverriddenEquals

        public SELF usingOverriddenEquals()
        By default the recursive comparison compare recursively all fields including the ones whose type have overridden equals except fields with java types (at some point we need to compare something!).

        This method instructs the recursive comparison to use overridden equals.

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
        
           // only compares number!
           @Override
           public boolean equals(final Object other) {
             if (!(other instanceof Address)) return false;
             Address castOther = (Address) other;
             return Objects.equals(number, castOther.number);
           }
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person sherlock2 = new Person("Sherlock", 1.80);
         sherlock2.home.address.street = "Butcher Street";
         sherlock2.home.address.number = 221;
        
         // assertion succeeds because Address equals does not compare street fields.
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .isEqualTo(sherlock2);
        
         // Assertion fails because:
         // - Address equals is not used.
         // - street fields are compared and differ.
         assertThat(sherlock).usingRecursiveComparison()
                             .isEqualTo(sherlock2);
        Returns:
        this RecursiveComparisonAssert to chain other methods.
        Since:
        3.17.0
      • ignoringOverriddenEqualsForFields

        public SELF ignoringOverriddenEqualsForFields​(String... fields)
        In case you have instructed the recursive to use overridden equals with usingOverriddenEquals(), this method allows to ignore overridden equals for the given fields (it adds them to the already registered ones).

        Since 3.17.0 all overridden equals so this method is only relevant if you have called usingOverriddenEquals() before.

        Nested fields can be specified by using dots like this: home.address.street

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
        
           // only compares number
           @Override
           public boolean equals(final Object other) {
             if (!(other instanceof Address)) return false;
             Address castOther = (Address) other;
             return Objects.equals(number, castOther.number);
           }
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person sherlock2 = new Person("Sherlock", 1.80);
         sherlock2.home.address.street = "Butcher Street";
         sherlock2.home.address.number = 221;
        
         // Assertion succeeds because:
         // - overridden equals are used
         // - Address has overridden equals and does not compare street fields.
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .isEqualTo(sherlock2);
        
         // ignoringOverriddenEqualsForFields force a recursive comparison on the given field
         // Assertion fails because:
         // - Address equals is not used.
         // - street fields are compared and differ.
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .ignoringOverriddenEqualsForFields("home.address")
                             .isEqualTo(sherlock2);
        Parameters:
        fields - the fields we want to force a recursive comparison on.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringOverriddenEqualsForTypes

        public SELF ignoringOverriddenEqualsForTypes​(Class<?>... types)
        By default the recursive comparison uses overridden equals methods to compare fields, this method allows to force a recursive comparison for all fields of the given types (it adds them to the already registered ones).

        Since 3.17.0 all overridden equals so this method is only relevant if you have called usingOverriddenEquals() before.

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
        
           // only compares number, ouch!
           @Override
           public boolean equals(final Object other) {
             if (!(other instanceof Address)) return false;
             Address castOther = (Address) other;
             return Objects.equals(number, castOther.number);
           }
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person sherlock2 = new Person("Sherlock", 1.80);
         sherlock2.home.address.street = "Butcher Street";
         sherlock2.home.address.number = 221;
        
         // Assertion succeeds because:
         // - overridden equals are used
         // - Address has overridden equals and does not compare street fields.
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .isEqualTo(sherlock2);
        
         // ignoringOverriddenEqualsForTypes force a recursive comparison on the given types.
         // Assertion fails because:
         // - Address equals is not used.
         // - street fields are compared and differ.
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .ignoringOverriddenEqualsForTypes(Address.class)
                             .isEqualTo(sherlock2);
        Parameters:
        types - the types we want to force a recursive comparison on.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringOverriddenEqualsForFieldsMatchingRegexes

        public SELF ignoringOverriddenEqualsForFieldsMatchingRegexes​(String... regexes)
        In case you have instructed the recursive to use overridden equals with usingOverriddenEquals(), this method allows to force a recursive comparison for the fields matching the given regexes (it adds them to the already registered ones).

        Since 3.17.0 all overridden equals so this method is only relevant if you have called usingOverriddenEquals() before.

        Nested fields can be specified by using dots like: home\.address\.street (\ is used to escape dots since they have a special meaning in regexes).

        Example:

         public class Person {
           String name;
           double height;
           Home home = new Home();
         }
        
         public class Home {
           Address address = new Address();
         }
        
         public static class Address {
           int number;
           String street;
        
           // only compares number, ouch!
           @Override
           public boolean equals(final Object other) {
             if (!(other instanceof Address)) return false;
             Address castOther = (Address) other;
             return Objects.equals(number, castOther.number);
           }
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.home.address.street = "Baker Street";
         sherlock.home.address.number = 221;
        
         Person sherlock2 = new Person("Sherlock", 1.80);
         sherlock2.home.address.street = "Butcher Street";
         sherlock2.home.address.number = 221;
        
         // assertion succeeds because overridden equals are used and thus street fields are mot compared
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .isEqualTo(sherlock2);
        
         // ignoringOverriddenEqualsForFields force a recursive comparison on the field matching the regex
         // now this assertion fails as we expect since the home.address.street fields differ
         assertThat(sherlock).usingRecursiveComparison()
                             .usingOverriddenEquals()
                             .ignoringOverriddenEqualsForFieldsMatchingRegexes("home.*")
                             .isEqualTo(sherlock2);
        Parameters:
        regexes - regexes used to specify the fields we want to force a recursive comparison on.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringCollectionOrder

        public SELF ignoringCollectionOrder()
        Makes the recursive comparison to ignore collection order in all fields in the object under test.

        Example:

         public class Person {
           String name;
           List<Person> friends = new ArrayList<>();
         }
        
         Person sherlock1 = new Person("Sherlock Holmes");
         sherlock1.friends.add(new Person("Dr. John Watson"));
         sherlock1.friends.add(new Person("Molly Hooper"));
        
         Person sherlock2 = new Person("Sherlock Holmes");
         sherlock2.friends.add(new Person("Molly Hooper"));
         sherlock2.friends.add(new Person("Dr. John Watson"));
        
         // assertion succeeds as all fields collection order is ignored in the comparison
         assertThat(sherlock1).usingRecursiveComparison()
                              .ignoringCollectionOrder()
                              .isEqualTo(sherlock2);
        
         // assertion fails as fields collection order is not ignored in the comparison
         assertThat(sherlock1).usingRecursiveComparison()
                              .isEqualTo(sherlock2);
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringCollectionOrderInFields

        public SELF ignoringCollectionOrderInFields​(String... fieldsToIgnoreCollectionOrder)
        Makes the recursive comparison to ignore collection order in the object under test specified fields. Nested fields can be specified like this: home.address.street.

        Example:

         public class Person {
           String name;
           List<Person> friends = new ArrayList<>();
           List<Person> enemies = new ArrayList<>();
         }
        
         Person sherlock1 = new Person("Sherlock Holmes");
         sherlock1.friends.add(new Person("Dr. John Watson"));
         sherlock1.friends.add(new Person("Molly Hooper"));
         sherlock1.enemies.add(new Person("Jim Moriarty"));
         sherlock1.enemies.add(new Person("Irene Adler"));
        
         Person sherlock2 = new Person("Sherlock Holmes");
         sherlock2.friends.add(new Person("Molly Hooper"));
         sherlock2.friends.add(new Person("Dr. John Watson"));
         sherlock2.enemies.add(new Person("Irene Adler"));
         sherlock2.enemies.add(new Person("Jim Moriarty"));
        
         // assertion succeeds as friends and enemies fields collection order is ignored in the comparison
         assertThat(sherlock1).usingRecursiveComparison()
                              .ignoringCollectionOrderInFields("friends", "enemies")
                              .isEqualTo(sherlock2);
        
         // assertion fails as enemies field collection order differ and it is not ignored
         assertThat(sherlock1).usingRecursiveComparison()
                              .ignoringCollectionOrderInFields("friends")
                              .isEqualTo(sherlock2);
        Parameters:
        fieldsToIgnoreCollectionOrder - the fields of the object under test to ignore collection order in the comparison.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • ignoringCollectionOrderInFieldsMatchingRegexes

        public SELF ignoringCollectionOrderInFieldsMatchingRegexes​(String... regexes)
        Makes the recursive comparison to ignore collection order in the object under test fields matching the specified regexes.

        Nested fields can be specified by using dots like this: home\.address\.street (\ is used to escape dots since they have a special meaning in regexes).

        Example:

         public class Person {
           String name;
           List<Person> friends = new ArrayList<>();
           List<Person> enemies = new ArrayList<>();
         }
        
         Person sherlock1 = new Person("Sherlock Holmes");
         sherlock1.friends.add(new Person("Dr. John Watson"));
         sherlock1.friends.add(new Person("Molly Hooper"));
         sherlock1.enemies.add(new Person("Jim Moriarty"));
         sherlock1.enemies.add(new Person("Irene Adler"));
        
         Person sherlock2 = new Person("Sherlock Holmes");
         sherlock2.friends.add(new Person("Molly Hooper"));
         sherlock2.friends.add(new Person("Dr. John Watson"));
         sherlock2.enemies.add(new Person("Irene Adler"));
         sherlock2.enemies.add(new Person("Jim Moriarty"));
        
         // assertion succeeds as friends and enemies fields collection order is ignored in the comparison
         assertThat(sherlock1).usingRecursiveComparison()
                              .ignoringCollectionOrderInFieldsMatchingRegexes("friend.", "enemie.")
                              .isEqualTo(sherlock2);
        
         // assertion fails as enemies field collection order differ and it is not ignored
         assertThat(sherlock1).usingRecursiveComparison()
                              .ignoringCollectionOrderInFields("friend.")
                              .isEqualTo(sherlock2);
        Parameters:
        regexes - regexes used to find the object under test fields to ignore collection order in the comparison.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • withStrictTypeChecking

        public SELF withStrictTypeChecking()
        Makes the recursive comparison to check that actual's type is compatible with expected's type (and do the same for each field).
        Compatible means that the expected's type is the same or a subclass of actual's type.

        Examples:

         public class Person {
           String name;
           double height;
           Person bestFriend;
         }
        
         Person sherlock = new Person("Sherlock", 1.80);
         sherlock.bestFriend = new Person("Watson", 1.70);
        
         Person sherlockClone = new Person("Sherlock", 1.80);
         sherlockClone.bestFriend = new Person("Watson", 1.70);
        
         // assertion succeeds as sherlock and sherlockClone have the same data and types
         assertThat(sherlock).usingRecursiveComparison()
                             .withStrictTypeChecking()
                             .isEqualTo(sherlockClone);
        
         // Let's now define a data structure similar to Person
        
         public class PersonDTO {
           String name;
           double height;
           PersonDTO bestFriend;
         }
        
         PersonDTO sherlockDto = new PersonDTO("Sherlock", 1.80);
         sherlockDto.bestFriend = new PersonDTO("Watson", 1.70);
        
         // assertion fails as Person and PersonDTO are not compatible even though they have the same data
         assertThat(sherlock).usingRecursiveComparison()
                             .withStrictTypeChecking()
                             .isEqualTo(noName);
        
         // Let's define a subclass of Person
        
         public class Detective extends Person {
           boolean busy;
         }
        
         Detective detectiveSherlock = new Detective("Sherlock", 1.80);
         detectiveSherlock.bestFriend = new Person("Watson", 1.70);
         detectiveSherlock.busy = true;
        
         // assertion succeeds as Detective inherits from Person and
         // only Person's fields are included into the comparison.
         assertThat(sherlock).usingRecursiveComparison()
                             .withStrictTypeChecking()
                             .isEqualTo(detectiveSherlock);
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • withEqualsForFields

        public SELF withEqualsForFields​(BiPredicate<?,​?> equals,
                                        String... fieldLocations)
        Allows to register a BiPredicate to compare fields with the given locations. A typical usage is for comparing double/float fields with a given precision.

        BiPredicates specified with this method have precedence over the ones registered with withEqualsForType(BiPredicate, Class) or the comparators registered with withComparatorForType(Comparator, Class).

        Note that registering a BiPredicate for a given field will override the previously registered Comparator (if any).

        The field locations must be specified from the root object, for example if Foo has a Bar field which has an id, one can register to a comparator for Bar's id by calling:

         withEqualsForFields(idBiPredicate, "foo.id", "foo.bar.id")

        Complete example:

         public class TolkienCharacter {
           String name;
           double height;
         }
        
         TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
         TolkienCharacter tallerFrodo = new TolkienCharacter("Frodo", 1.3);
         TolkienCharacter reallyTallFrodo = new TolkienCharacter("Frodo", 1.9);
        
         BiPredicate<Double, Double> closeEnough = (d1, d2) -> Math.abs(d1 - d2) <= 0.5;
        
         // assertion succeeds
         assertThat(frodo).usingRecursiveComparison()
                          .withEqualsForFields(closeEnough, "height")
                          .isEqualTo(tallerFrodo);
        
         // assertion fails
         assertThat(frodo).usingRecursiveComparison()
                          .withEqualsForFields(closeEnough, "height")
                          .isEqualTo(reallyTallFrodo);
        Parameters:
        equals - the BiPredicate to use to compare the given fields
        fieldLocations - the location from the root object of the fields the BiPredicate should be used for
        Returns:
        this RecursiveComparisonAssert to chain other methods.
        Throws:
        NullPointerException - if the given BiPredicate is null.
      • withComparatorForFields

        public SELF withComparatorForFields​(Comparator<?> comparator,
                                            String... fieldLocations)
        Allows to register a comparator to compare fields with the given locations. A typical usage is for comparing double/float fields with a given precision.

        Comparators registered with this method have precedence over comparators registered with withComparatorForType(Comparator, Class) or BiPredicate registered with withEqualsForType(BiPredicate, Class).

        The field locations must be specified from the root object, for example if Foo has a Bar field which has an id, one can register to a comparator for Bar's id by calling:

         withComparatorForFields(idComparator, "foo.id", "foo.bar.id")

        Note that registering a Comparator for a given field will override the previously registered BiPredicate/Comparator (if any).

        Complete example:

         public class TolkienCharacter {
           String name;
           double height;
         }
        
         TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
         TolkienCharacter tallerFrodo = new TolkienCharacter("Frodo", 1.3);
         TolkienCharacter reallyTallFrodo = new TolkienCharacter("Frodo", 1.9);
        
         Comparator<Double> closeEnough = (d1, d2) -> Math.abs(d1 - d2) <= 0.5 ? 0 : 1;
        
         // assertion succeeds
         assertThat(frodo).usingRecursiveComparison()
                          .withComparatorForFields(closeEnough, "height")
                          .isEqualTo(tallerFrodo);
        
         // assertion fails
         assertThat(frodo).usingRecursiveComparison()
                          .withComparatorForFields(closeEnough, "height")
                          .isEqualTo(reallyTallFrodo);
        Parameters:
        comparator - the Comparator to use to compare the given fields
        fieldLocations - the location from the root object of the fields the comparator should be used for
        Returns:
        this RecursiveComparisonAssert to chain other methods.
        Throws:
        NullPointerException - if the given comparator is null.
      • withComparatorForType

        public <T> SELF withComparatorForType​(Comparator<? super T> comparator,
                                              Class<T> type)
        Allows to register a comparator to compare the fields with the given type. A typical usage is for comparing double/float fields with a given precision.

        Comparators registered with this method have less precedence than comparators registered with withComparatorForFields(Comparator, String...) or BiPredicate registered with withEqualsForFields(BiPredicate, String...).

        Note that registering a Comparator for a given type will override the previously registered BiPredicate/Comparator (if any).

        Example:

         public class TolkienCharacter {
           String name;
           double height;
         }
        
         TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
         TolkienCharacter tallerFrodo = new TolkienCharacter("Frodo", 1.3);
         TolkienCharacter reallyTallFrodo = new TolkienCharacter("Frodo", 1.9);
        
         Comparator<Double> closeEnough = (d1, d2) -> Math.abs(d1 - d2) <= 0.5 ? 0 : 1;
        
         // assertion succeeds
         assertThat(frodo).usingRecursiveComparison()
                          .withComparatorForType(closeEnough, Double.class)
                          .isEqualTo(tallerFrodo);
        
         // assertion fails
         assertThat(frodo).usingRecursiveComparison()
                          .withComparatorForType(closeEnough, Double.class)
                          .isEqualTo(reallyTallFrodo);
        Type Parameters:
        T - the class type to register a comparator for
        Parameters:
        comparator - the Comparator to use to compare the given fields
        type - the type to be compared with the given comparator.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
        Throws:
        NullPointerException - if the given comparator is null.
      • withEqualsForType

        public <T> SELF withEqualsForType​(BiPredicate<? super T,​? super T> equals,
                                          Class<T> type)
        Allows to register a BiPredicate to compare the fields with the given type. A typical usage is for comparing double/float fields with a given precision.

        BiPredicates registered with this method have less precedence than the one registered with withEqualsForFields(BiPredicate, String...) or comparators registered with withComparatorForFields(Comparator, String...).

        Note that registering a BiPredicate for a given type will override the previously registered BiPredicate/Comparator (if any).

        Example:

         public class TolkienCharacter {
           String name;
           double height;
         }
        
         TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
         TolkienCharacter tallerFrodo = new TolkienCharacter("Frodo", 1.3);
         TolkienCharacter reallyTallFrodo = new TolkienCharacter("Frodo", 1.9);
        
         BiPredicate<Double, Double> closeEnough = (d1, d2) -> Math.abs(d1 - d2) <= 0.5;
        
         // assertion succeeds
         assertThat(frodo).usingRecursiveComparison()
                          .withEqualsForType(closeEnough, Double.class)
                          .isEqualTo(tallerFrodo);
        
         // assertion fails
         assertThat(frodo).usingRecursiveComparison()
                          .withEqualsForType(closeEnough, Double.class)
                          .isEqualTo(reallyTallFrodo);
        Type Parameters:
        T - the class type to register a BiPredicate for
        Parameters:
        equals - the BiPredicate to use to compare the given fields
        type - the type to be compared with the given comparator.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
        Throws:
        NullPointerException - if the given BiPredicate is null.
      • withErrorMessageForFields

        public SELF withErrorMessageForFields​(String message,
                                              String... fieldLocations)
        Overrides an error message which would be shown when differences in the given fields while comparison occurred with the giving error message.

        The fields must be specified from the root object, for example if Foo has a Bar field and both have an id field, one can register a message for Foo and Bar's id by calling:

         withErrorMessageForFields("some message", "foo.id", "foo.bar.id")

        Messages registered with this method have precedence over the ones registered with withErrorMessageForType(String, Class).

        In case of null as message the default error message will be used (See ComparisonDifference.DEFAULT_TEMPLATE).

        Example:

         public class TolkienCharacter {
           String name;
           double height;
         }
        
         TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
         TolkienCharacter tallerFrodo = new TolkienCharacter("Frodon", 1.4);
        
         String message = "The field 'height' differ.";
        
         // assertion fails
         assertThat(frodo).usingRecursiveComparison()
                          .withErrorMessageForFields(message, "height")
                          .isEqualTo(tallerFrodo);
        and the error will report the height field with the given overridden message instead of the one computed by AssertJ as with the name error:
        
         Expecting actual:
           TolkienCharacter [name=Frodo, height=1.2]
         to be equal to:
           TolkienCharacter [name=Frodon, height=1.4]
         when recursively comparing field by field, but found the following 2 differences:
         
         The field 'height' differ.
         
         field/property 'name' differ:
         - actual value  : "Frodo"
         - expected value: "Frodon"
         
         The recursive comparison was performed with this configuration:
         - no overridden equals methods were used in the comparison (except for java types)
         - these types were compared with the following comparators:
           - java.lang.Double -> DoubleComparator[precision=1.0E-15]
           - java.lang.Float -> FloatComparator[precision=1.0E-6]
           - java.nio.file.Path -> lexicographic comparator (Path natural order)
         - actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).
         - these fields had overridden error messages:
           - height
        Parameters:
        message - the error message that will be thrown when comparison error occurred.
        fieldLocations - the fields the error message should be used for.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • withErrorMessageForType

        public SELF withErrorMessageForType​(String message,
                                            Class<?> type)
        Overrides an error message which would be shown when differences for the giving type while comparison occurred with the giving error message.

        Message registered with this method have less precedence than the ones registered with withErrorMessageForFields(String, String...).

        In case of null as message the default error message will be used (See ComparisonDifference.DEFAULT_TEMPLATE).

        Example:

         public class TolkienCharacter {
           String name;
           double height;
         }
        
         TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
         TolkienCharacter tallerFrodo = new TolkienCharacter("Frodon", 1.4);
        
         String message = "Double field differ.";
        
         // assertion fails
         assertThat(frodo).usingRecursiveComparison()
                          .withErrorMessageForType(message, Double.class)
                          .isEqualTo(tallerFrodo);
        and the error will report the height field with the given overridden message instead of the one computed by AssertJ as with the name error:
        
         Expecting actual:
           TolkienCharacter [name=Frodo, height=1.2]
         to be equal to:
           TolkienCharacter [name=Frodon, height=1.4]
         when recursively comparing field by field, but found the following 2 differences:
         
         Double field differ.
         
         field/property 'name' differ:
         - actual value  : "Frodo"
         - expected value: "Frodon"
         
         The recursive comparison was performed with this configuration:
         - no overridden equals methods were used in the comparison (except for java types)
         - these types were compared with the following comparators:
           - java.lang.Double -> DoubleComparator[precision=1.0E-15]
           - java.lang.Float -> FloatComparator[precision=1.0E-6]
           - java.nio.file.Path -> lexicographic comparator (Path natural order)
         - actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).
         - these types had overridden error messages:
           - height
        Parameters:
        message - the error message that will be thrown when comparison error occurred.
        type - the type the error message should be used for.
        Returns:
        this RecursiveComparisonAssert to chain other methods.
      • withTypeComparators

        SELF withTypeComparators​(org.assertj.core.internal.TypeComparators typeComparators)