|
26 | 26 | import java.util.function.Function;
|
27 | 27 | import java.util.stream.Stream;
|
28 | 28 |
|
| 29 | +import org.assertj.core.annotations.Beta; |
| 30 | +import org.assertj.core.api.recursive.comparison.RecursiveComparisonConfiguration; |
29 | 31 | import org.assertj.core.description.Description;
|
30 | 32 | import org.assertj.core.groups.Tuple;
|
31 | 33 | import org.assertj.core.internal.TypeComparators;
|
@@ -672,7 +674,7 @@ public AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object
|
672 | 674 | }
|
673 | 675 |
|
674 | 676 | /**
|
675 |
| - * Asserts that the object under test (actual) is equal to the given object based on recursive a property/field by property/field comparison (including |
| 677 | + * Asserts that the object under test (actual) is equal to the given object based on a recursive property/field by property/field comparison (including |
676 | 678 | * inherited ones). This can be useful if actual's {@code equals} implementation does not suit you.
|
677 | 679 | * The recursive property/field comparison is <b>not</b> applied on fields having a custom {@code equals} implementation, i.e.
|
678 | 680 | * the overridden {@code equals} method will be used instead of a field by field comparison.
|
@@ -770,6 +772,74 @@ public <T> SELF returns(T expected, Function<ACTUAL, T> from) {
|
770 | 772 | return myself;
|
771 | 773 | }
|
772 | 774 |
|
| 775 | + /** |
| 776 | + * Enable using a recursive field by field comparison strategy when calling the chained {@link RecursiveComparisonAssert#isEqualTo(Object) isEqualTo} assertion. |
| 777 | + * <p> |
| 778 | + * Example: |
| 779 | + * <pre><code class='java'> public class Person { |
| 780 | + * String name; |
| 781 | + * double height; |
| 782 | + * Home home = new Home(); |
| 783 | + * } |
| 784 | + * |
| 785 | + * public class Home { |
| 786 | + * Address address = new Address(); |
| 787 | + * Date ownedSince; |
| 788 | + * } |
| 789 | + * |
| 790 | + * public static class Address { |
| 791 | + * int number; |
| 792 | + * String street; |
| 793 | + * } |
| 794 | + * |
| 795 | + * Person sherlock = new Person("Sherlock", 1.80); |
| 796 | + * sherlock.home.ownedSince = new Date(123); |
| 797 | + * sherlock.home.address.street = "Baker Street"; |
| 798 | + * sherlock.home.address.number = 221; |
| 799 | + * |
| 800 | + * Person sherlock2 = new Person("Sherlock", 1.80); |
| 801 | + * sherlock2.home.ownedSince = new Date(123); |
| 802 | + * sherlock2.home.address.street = "Baker Street"; |
| 803 | + * sherlock2.home.address.number = 221; |
| 804 | + * |
| 805 | + * // assertion succeeds as the data of both objects are the same. |
| 806 | + * assertThat(sherlock).usingRecursiveComparison() |
| 807 | + * .isEqualTo(sherlock2); |
| 808 | + * |
| 809 | + * // assertion fails because sherlock.equals(sherlock2) is false. |
| 810 | + * assertThat(sherlock).isEqualTo(sherlock2);</code></pre> |
| 811 | + * <p> |
| 812 | + * The recursive comparison is performed according to the default {@link RecursiveComparisonConfiguration} that is: |
| 813 | + * <ul> |
| 814 | + * <li>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 {@link RecursiveComparisonAssert#withStrictTypeChecking() withStrictTypeChecking()} to change that behavior). </li> |
| 815 | + * <li>overridden equals methods were used in the comparison (unless stated otherwise)</li> |
| 816 | + * <li>these types were compared with the following comparators: </li> |
| 817 | + * <ul> |
| 818 | + * <li>java.lang.Double -> DoubleComparator[precision=1.0E-15] </li> |
| 819 | + * <li>java.lang.Float -> FloatComparator[precision=1.0E-6] </li> |
| 820 | + * <li>any comparators previously registered with {@link AbstractObjectAssert#usingComparatorForType(Comparator, Class)} </li> |
| 821 | + * </ul> |
| 822 | + * </ul> |
| 823 | + * |
| 824 | + * @return a new {@link RecursiveComparisonAssert} instance |
| 825 | + */ |
| 826 | + @Beta |
| 827 | + public RecursiveComparisonAssert<?> usingRecursiveComparison() { |
| 828 | + return usingRecursiveComparison(new RecursiveComparisonConfiguration()); |
| 829 | + } |
| 830 | + |
| 831 | + /** |
| 832 | + * Same as {@link #usingRecursiveComparison()} but allows to specify your own {@link RecursiveComparisonConfiguration}. |
| 833 | + * @param recursiveComparisonConfiguration the {@link RecursiveComparisonConfiguration} used in the chained {@link RecursiveComparisonAssert#isEqualTo(Object) isEqualTo} assertion. |
| 834 | + * |
| 835 | + * @return a new {@link RecursiveComparisonAssert} instance built with the given {@link RecursiveComparisonConfiguration}. |
| 836 | + */ |
| 837 | + @Beta |
| 838 | + public RecursiveComparisonAssert<?> usingRecursiveComparison(RecursiveComparisonConfiguration recursiveComparisonConfiguration) { |
| 839 | + return new RecursiveComparisonAssert<>(actual, recursiveComparisonConfiguration).withAssertionState(myself) |
| 840 | + .withTypeComparators(comparatorByType); |
| 841 | + } |
| 842 | + |
773 | 843 | // override for proxyable friendly AbstractObjectAssert
|
774 | 844 | protected AbstractObjectAssert<?, ?> newObjectAssert(Object objectUnderTest) {
|
775 | 845 | return new ObjectAssert<>(objectUnderTest);
|
|
0 commit comments