Skip to content

Commit 6f62ebe

Browse files
Use registered comparators by type in recursive comparison.
1 parent 5b729e4 commit 6f62ebe

9 files changed

+347
-25
lines changed

src/main/java/org/assertj/core/api/recursive/comparison/RecursiveComparisonConfiguration.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import static java.lang.String.format;
1616
import static java.util.stream.Collectors.toList;
1717
import static org.assertj.core.configuration.ConfigurationProvider.CONFIGURATION_PROVIDER;
18+
import static org.assertj.core.internal.TypeComparators.defaultTypeComparators;
1819
import static org.assertj.core.util.Lists.list;
1920
import static org.assertj.core.util.Strings.join;
2021

@@ -32,6 +33,7 @@
3233
import org.assertj.core.presentation.Representation;
3334
import org.assertj.core.util.VisibleForTesting;
3435

36+
// TODO registered comparators vs ignored overridden equals test
3537
@Beta
3638
public class RecursiveComparisonConfiguration {
3739

@@ -47,29 +49,34 @@ public class RecursiveComparisonConfiguration {
4749
private List<FieldLocation> ignoredOverriddenEqualsForFields = new ArrayList<>();
4850
private List<Pattern> ignoredOverriddenEqualsRegexes = new ArrayList<>();
4951

50-
private TypeComparators comparatorForTypes = new TypeComparators();
52+
private TypeComparators comparatorForTypes = defaultTypeComparators();
5153
// private FieldComparators comparatorForFields = new FieldComparators();
5254

5355
public Comparator getComparatorForField(String fieldName) {
5456
return null;
5557
}
5658

5759
public Comparator getComparatorForType(Class fieldType) {
58-
return null;
60+
return comparatorForTypes.get(fieldType);
5961
}
6062

6163
public boolean hasComparatorForField(String fieldName) {
6264
return false;
6365
}
6466

6567
public boolean hasComparatorForType(Class<?> keyType) {
66-
return false;
68+
return comparatorForTypes.get(keyType) != null;
6769
}
6870

6971
public boolean hasNoCustomComparators() {
7072
return false;
7173
}
7274

75+
@VisibleForTesting
76+
TypeComparators getComparatorForTypes() {
77+
return comparatorForTypes;
78+
}
79+
7380
/**
7481
* Sets whether actual null fields are ignored in the recursive comparison.
7582
* <p>

src/main/java/org/assertj/core/api/recursive/comparison/RecursiveComparisonDifferenceCalculator.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,12 @@ private static List<ComparisonDifference> determineDifferences(Object actual, Ob
9898

9999
// Custom comparators take precedence over all other type of comparison
100100
if (hasCustomComparator(dualKey, recursiveComparisonConfiguration)) {
101-
if (propertyOrFieldValuesAreEqual(key1, key2, dualKey.getConcatenatedPath(), recursiveComparisonConfiguration))
102-
continue;
101+
if (!propertyOrFieldValuesAreEqual(key1, key2, dualKey.getConcatenatedPath(), recursiveComparisonConfiguration)) {
102+
// fields were not the same according to the custom comparator
103+
differences.add(new ComparisonDifference(currentPath, key1, key2));
104+
}
105+
// since there was a custom comparator we don't need to inspect the fields
106+
continue;
103107
}
104108

105109
if (key1 == null || key2 == null) {
@@ -641,8 +645,8 @@ static boolean hasCustomHashCode(Class<?> c) {
641645
}
642646

643647
@SuppressWarnings({ "unchecked", "rawtypes" })
644-
static boolean propertyOrFieldValuesAreEqual(Object actualFieldValue, Object otherFieldValue, String fieldName,
645-
RecursiveComparisonConfiguration recursiveComparisonConfiguration) {
648+
private static boolean propertyOrFieldValuesAreEqual(Object actualFieldValue, Object otherFieldValue, String fieldName,
649+
RecursiveComparisonConfiguration recursiveComparisonConfiguration) {
646650
// no need to look into comparators if objects are the same
647651
if (actualFieldValue == otherFieldValue) return true;
648652
// check field comparators as they take precedence over type comparators
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
3+
* the License. You may obtain a copy of the License at
4+
*
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
* specific language governing permissions and limitations under the License.
10+
*
11+
* Copyright 2012-2018 the original author or authors.
12+
*/
13+
package org.assertj.core.api.recursive.comparison;
14+
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
import static org.assertj.core.internal.TypeComparators.defaultTypeComparators;
17+
18+
import org.assertj.core.groups.Tuple;
19+
import org.assertj.core.internal.TypeComparators;
20+
import org.assertj.core.test.AlwaysEqualComparator;
21+
import org.assertj.core.util.AbsValueComparator;
22+
import org.junit.jupiter.api.BeforeEach;
23+
import org.junit.jupiter.api.Test;
24+
25+
public class RecursiveComparisonConfiguration_comparatorByType_Test {
26+
27+
private RecursiveComparisonConfiguration recursiveComparisonConfiguration;
28+
29+
@BeforeEach
30+
public void setup() {
31+
recursiveComparisonConfiguration = new RecursiveComparisonConfiguration();
32+
}
33+
34+
@Test
35+
public void should_have_default_comparator_by_types() {
36+
// WHEN
37+
TypeComparators typeComparators = recursiveComparisonConfiguration.getComparatorForTypes();
38+
// THEN
39+
assertThat(typeComparators).isEqualTo(defaultTypeComparators());
40+
}
41+
42+
@Test
43+
public void should_register_given_comparator_per_types() {
44+
// GIVEN
45+
AbsValueComparator<Integer> integerComparator = new AbsValueComparator<>();
46+
recursiveComparisonConfiguration.registerComparatorForType(Integer.class, integerComparator);
47+
recursiveComparisonConfiguration.registerComparatorForType(Tuple.class, AlwaysEqualComparator.ALWAY_EQUALS_TUPLE);
48+
// THEN
49+
assertThat(recursiveComparisonConfiguration.getComparatorForType(Integer.class)).isSameAs(integerComparator);
50+
assertThat(recursiveComparisonConfiguration.getComparatorForType(Tuple.class)).isSameAs(AlwaysEqualComparator.ALWAY_EQUALS_TUPLE);
51+
}
52+
53+
}

src/test/java/org/assertj/core/api/recursive/comparison/RecursiveComparisonConfiguration_multiLineDescription_Test.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void should_show_the_ignored_overridden_equals_methods_fields() {
101101
}
102102

103103
@Test
104-
public void should_show_the_registered_comparator_by_types() {
104+
public void should_show_the_registered_comparator_by_types_and_the_default_ones() {
105105
// WHEN
106106
recursiveComparisonConfiguration.registerComparatorForType(Integer.class, new AbsValueComparator<>());
107107
recursiveComparisonConfiguration.registerComparatorForType(Tuple.class, AlwaysEqualComparator.ALWAY_EQUALS_TUPLE);
@@ -110,6 +110,8 @@ public void should_show_the_registered_comparator_by_types() {
110110
// @format:off
111111
assertThat(multiLineDescription).contains(format(
112112
"- the following comparators were used in the comparison for these types:%n" +
113+
"--- java.lang.Double -> DoubleComparator[precision=1.0E-15]%n" +
114+
"--- java.lang.Float -> FloatComparator[precision=1.0E-6]%n" +
113115
"--- java.lang.Integer -> AbsValueComparator%n" +
114116
"--- org.assertj.core.groups.Tuple -> AlwaysEqualComparator%n"));
115117
// @format:on
@@ -138,6 +140,8 @@ public void should_show_a_complete_multiline_description() {
138140
"--- the following types: java.lang.String, com.google.common.collect.Multimap%n" +
139141
"--- the types matching the following regexes: .*oo, .ar, oo.ba%n" +
140142
"- the following comparators were used in the comparison for these types:%n" +
143+
"--- java.lang.Double -> DoubleComparator[precision=1.0E-15]%n" +
144+
"--- java.lang.Float -> FloatComparator[precision=1.0E-6]%n" +
141145
"--- java.lang.Integer -> AbsValueComparator%n" +
142146
"--- org.assertj.core.groups.Tuple -> AlwaysEqualComparator%n"));
143147
// @format:on

src/test/java/org/assertj/core/internal/objects/Objects_assertIsEqualToUsingRecursiveComparison_BaseTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void verifyShouldBeEqualByComparingFieldByFieldRecursivelyCall(Object actual, Ob
4242
INFO.representation()));
4343
}
4444

45-
void compareRecusively(Object actual, Object expected,
45+
void areEqualsByRecursiveComparison(Object actual, Object expected,
4646
RecursiveComparisonConfiguration recursiveComparisonConfiguration) {
4747
objects.assertIsEqualToUsingRecursiveComparison(INFO, actual, expected, recursiveComparisonConfiguration);
4848
}

src/test/java/org/assertj/core/internal/objects/Objects_assertIsEqualToUsingRecursiveComparison_Test.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public void should_pass_when_actual_and_expected_are_null() {
7070
Person actual = null;
7171
Person expected = null;
7272
// THEN
73-
compareRecusively(actual, expected, recursiveComparisonConfiguration);
73+
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
7474
}
7575

7676
@Test
@@ -79,7 +79,7 @@ public void should_fail_when_actual_is_null_and_expected_is_not() {
7979
Person actual = null;
8080
Person expected = new Person();
8181
// WHEN
82-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
82+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
8383
// THEN
8484
verify(failures).failure(INFO, shouldNotBeNull());
8585
}
@@ -90,7 +90,7 @@ public void should_fail_when_actual_is_not_null_and_expected_is() {
9090
Person actual = new Person();
9191
Person expected = null;
9292
// WHEN
93-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
93+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
9494
// THEN
9595
verify(failures).failure(INFO, shouldBeEqual(actual, null, objects.getComparisonStrategy(), INFO.representation()));
9696
}
@@ -101,7 +101,7 @@ public void should_fail_when_actual_is_not_null_and_expected_is() {
101101
public void should_pass_for_objects_with_the_same_data_when_using_the_default_recursive_comparison(Object actual,
102102
Object expected,
103103
String testDescription) {
104-
compareRecusively(actual, expected, recursiveComparisonConfiguration);
104+
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
105105
}
106106

107107
@SuppressWarnings("unused")
@@ -132,7 +132,7 @@ public void should_pass_for_objects_with_the_same_data_when_all_null_fields_are_
132132
// GIVEN
133133
recursiveComparisonConfiguration.setIgnoreAllActualNullFields(true);
134134
// THEN
135-
compareRecusively(actual, expected, recursiveComparisonConfiguration);
135+
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
136136
}
137137

138138
@Test
@@ -146,7 +146,7 @@ public void should_fail_when_actual_differs_from_expected_even_when_all_null_fie
146146
expected.home.address.number = 2;
147147
recursiveComparisonConfiguration.setIgnoreAllActualNullFields(true);
148148
// WHEN
149-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
149+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
150150
// THEN
151151
ComparisonDifference comparisonDifference = new ComparisonDifference(list("home.address.number"), 1, 2);
152152
verifyShouldBeEqualByComparingFieldByFieldRecursivelyCall(actual, expected, comparisonDifference);
@@ -213,7 +213,7 @@ public void should_pass_for_objects_with_the_same_data_when_given_fields_are_ign
213213
// GIVEN
214214
recursiveComparisonConfiguration.ignoreFields(ignoredFields.toArray(new String[0]));
215215
// THEN
216-
compareRecusively(actual, expected, recursiveComparisonConfiguration);
216+
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
217217
}
218218

219219
@SuppressWarnings("unused")
@@ -281,7 +281,7 @@ public void should_fail_when_actual_differs_from_expected_even_when_some_fields_
281281
recursiveComparisonConfiguration.ignoreFields("name", "home.address.number");
282282

283283
// WHEN
284-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
284+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
285285

286286
// THEN
287287
ComparisonDifference dateOfBirthDifference = diff("dateOfBirth", actual.dateOfBirth, expected.dateOfBirth);
@@ -317,7 +317,7 @@ public void should_fail_when_actual_differs_from_expected_even_when_some_fields_
317317
recursiveComparisonConfiguration.ignoreFieldsByRegexes(".*name", ".*home.*number");
318318

319319
// WHEN
320-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
320+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
321321

322322
// THEN
323323
ComparisonDifference dateOfBirthDifference = diff("dateOfBirth", actual.dateOfBirth, expected.dateOfBirth);

src/test/java/org/assertj/core/internal/objects/Objects_assertIsEqualToUsingRecursiveComparison_ignoreOverriddenEquals_Test.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void should_pass_when_comparison_ignores_overridden_equals_methods_by_reg
4444
// GIVEN
4545
recursiveComparisonConfiguration.ignoreOverriddenEqualsByRegexes(regexes.toArray(new String[0]));
4646
// THEN
47-
compareRecusively(actual, expected, recursiveComparisonConfiguration);
47+
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
4848
}
4949

5050
@SuppressWarnings("unused")
@@ -88,7 +88,7 @@ public void should_fail_when_actual_differs_from_expected_as_some_overridden_equ
8888
recursiveComparisonConfiguration.ignoreOverriddenEqualsByRegexes(".*AlwaysEqualPerson", ".*AlwaysEqualAddress");
8989

9090
// WHEN
91-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
91+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
9292

9393
// THEN
9494
ComparisonDifference neighbourNameDifference = diff("neighbour.name", actual.neighbour.name, expected.neighbour.name);
@@ -110,7 +110,7 @@ public void should_pass_when_comparison_ignores_overridden_equals_methods_by_typ
110110
// GIVEN
111111
recursiveComparisonConfiguration.ignoreOverriddenEqualsForTypes(types.toArray(new Class[0]));
112112
// THEN
113-
compareRecusively(actual, expected, recursiveComparisonConfiguration);
113+
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
114114
}
115115

116116
@SuppressWarnings("unused")
@@ -152,7 +152,7 @@ public void should_fail_when_actual_differs_from_expected_as_some_overridden_equ
152152
recursiveComparisonConfiguration.ignoreOverriddenEqualsForTypes(AlwaysEqualPerson.class, AlwaysEqualAddress.class);
153153

154154
// WHEN
155-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
155+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
156156

157157
// THEN
158158
ComparisonDifference neighbourNameDifference = diff("neighbour.name", actual.neighbour.name, expected.neighbour.name);
@@ -174,7 +174,7 @@ public void should_pass_when_comparison_ignores_overridden_equals_methods_by_fie
174174
// GIVEN
175175
recursiveComparisonConfiguration.ignoreOverriddenEqualsForFields(fields.toArray(new String[0]));
176176
// THEN
177-
compareRecusively(actual, expected, recursiveComparisonConfiguration);
177+
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
178178
}
179179

180180
@SuppressWarnings("unused")
@@ -216,7 +216,7 @@ public void should_fail_when_actual_differs_from_expected_as_some_overridden_equ
216216
recursiveComparisonConfiguration.ignoreOverriddenEqualsForFields("neighbour", "neighbour.home.address");
217217

218218
// WHEN
219-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
219+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
220220

221221
// THEN
222222
ComparisonDifference neighbourNameDifference = diff("neighbour.name", actual.neighbour.name, expected.neighbour.name);
@@ -235,7 +235,7 @@ public void ignoring_overridden_equals_methods_only_applies_on_fields_but_not_on
235235
expected.name = "Jack";
236236
// THEN
237237
// would have succeeded if we had used AlwaysEqualPerson equals method
238-
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
238+
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
239239
}
240240

241241
}

0 commit comments

Comments
 (0)