Skip to content

Commit

Permalink
Use registered comparators by type in recursive comparison.
Browse files Browse the repository at this point in the history
  • Loading branch information
joel-costigliola committed Feb 13, 2019
1 parent 5b729e4 commit 6f62ebe
Show file tree
Hide file tree
Showing 9 changed files with 347 additions and 25 deletions.
Expand Up @@ -15,6 +15,7 @@
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.configuration.ConfigurationProvider.CONFIGURATION_PROVIDER;
import static org.assertj.core.internal.TypeComparators.defaultTypeComparators;
import static org.assertj.core.util.Lists.list;
import static org.assertj.core.util.Strings.join;

Expand All @@ -32,6 +33,7 @@
import org.assertj.core.presentation.Representation;
import org.assertj.core.util.VisibleForTesting;

// TODO registered comparators vs ignored overridden equals test
@Beta
public class RecursiveComparisonConfiguration {

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

private TypeComparators comparatorForTypes = new TypeComparators();
private TypeComparators comparatorForTypes = defaultTypeComparators();
// private FieldComparators comparatorForFields = new FieldComparators();

public Comparator getComparatorForField(String fieldName) {
return null;
}

public Comparator getComparatorForType(Class fieldType) {
return null;
return comparatorForTypes.get(fieldType);
}

public boolean hasComparatorForField(String fieldName) {
return false;
}

public boolean hasComparatorForType(Class<?> keyType) {
return false;
return comparatorForTypes.get(keyType) != null;
}

public boolean hasNoCustomComparators() {
return false;
}

@VisibleForTesting
TypeComparators getComparatorForTypes() {
return comparatorForTypes;
}

/**
* Sets whether actual null fields are ignored in the recursive comparison.
* <p>
Expand Down
Expand Up @@ -98,8 +98,12 @@ private static List<ComparisonDifference> determineDifferences(Object actual, Ob

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

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

@SuppressWarnings({ "unchecked", "rawtypes" })
static boolean propertyOrFieldValuesAreEqual(Object actualFieldValue, Object otherFieldValue, String fieldName,
RecursiveComparisonConfiguration recursiveComparisonConfiguration) {
private static boolean propertyOrFieldValuesAreEqual(Object actualFieldValue, Object otherFieldValue, String fieldName,
RecursiveComparisonConfiguration recursiveComparisonConfiguration) {
// no need to look into comparators if objects are the same
if (actualFieldValue == otherFieldValue) return true;
// check field comparators as they take precedence over type comparators
Expand Down
@@ -0,0 +1,53 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2018 the original author or authors.
*/
package org.assertj.core.api.recursive.comparison;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.internal.TypeComparators.defaultTypeComparators;

import org.assertj.core.groups.Tuple;
import org.assertj.core.internal.TypeComparators;
import org.assertj.core.test.AlwaysEqualComparator;
import org.assertj.core.util.AbsValueComparator;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class RecursiveComparisonConfiguration_comparatorByType_Test {

private RecursiveComparisonConfiguration recursiveComparisonConfiguration;

@BeforeEach
public void setup() {
recursiveComparisonConfiguration = new RecursiveComparisonConfiguration();
}

@Test
public void should_have_default_comparator_by_types() {
// WHEN
TypeComparators typeComparators = recursiveComparisonConfiguration.getComparatorForTypes();
// THEN
assertThat(typeComparators).isEqualTo(defaultTypeComparators());
}

@Test
public void should_register_given_comparator_per_types() {
// GIVEN
AbsValueComparator<Integer> integerComparator = new AbsValueComparator<>();
recursiveComparisonConfiguration.registerComparatorForType(Integer.class, integerComparator);
recursiveComparisonConfiguration.registerComparatorForType(Tuple.class, AlwaysEqualComparator.ALWAY_EQUALS_TUPLE);
// THEN
assertThat(recursiveComparisonConfiguration.getComparatorForType(Integer.class)).isSameAs(integerComparator);
assertThat(recursiveComparisonConfiguration.getComparatorForType(Tuple.class)).isSameAs(AlwaysEqualComparator.ALWAY_EQUALS_TUPLE);
}

}
Expand Up @@ -101,7 +101,7 @@ public void should_show_the_ignored_overridden_equals_methods_fields() {
}

@Test
public void should_show_the_registered_comparator_by_types() {
public void should_show_the_registered_comparator_by_types_and_the_default_ones() {
// WHEN
recursiveComparisonConfiguration.registerComparatorForType(Integer.class, new AbsValueComparator<>());
recursiveComparisonConfiguration.registerComparatorForType(Tuple.class, AlwaysEqualComparator.ALWAY_EQUALS_TUPLE);
Expand All @@ -110,6 +110,8 @@ public void should_show_the_registered_comparator_by_types() {
// @format:off
assertThat(multiLineDescription).contains(format(
"- the following comparators were used in the comparison for these types:%n" +
"--- java.lang.Double -> DoubleComparator[precision=1.0E-15]%n" +
"--- java.lang.Float -> FloatComparator[precision=1.0E-6]%n" +
"--- java.lang.Integer -> AbsValueComparator%n" +
"--- org.assertj.core.groups.Tuple -> AlwaysEqualComparator%n"));
// @format:on
Expand Down Expand Up @@ -138,6 +140,8 @@ public void should_show_a_complete_multiline_description() {
"--- the following types: java.lang.String, com.google.common.collect.Multimap%n" +
"--- the types matching the following regexes: .*oo, .ar, oo.ba%n" +
"- the following comparators were used in the comparison for these types:%n" +
"--- java.lang.Double -> DoubleComparator[precision=1.0E-15]%n" +
"--- java.lang.Float -> FloatComparator[precision=1.0E-6]%n" +
"--- java.lang.Integer -> AbsValueComparator%n" +
"--- org.assertj.core.groups.Tuple -> AlwaysEqualComparator%n"));
// @format:on
Expand Down
Expand Up @@ -42,7 +42,7 @@ void verifyShouldBeEqualByComparingFieldByFieldRecursivelyCall(Object actual, Ob
INFO.representation()));
}

void compareRecusively(Object actual, Object expected,
void areEqualsByRecursiveComparison(Object actual, Object expected,
RecursiveComparisonConfiguration recursiveComparisonConfiguration) {
objects.assertIsEqualToUsingRecursiveComparison(INFO, actual, expected, recursiveComparisonConfiguration);
}
Expand Down
Expand Up @@ -70,7 +70,7 @@ public void should_pass_when_actual_and_expected_are_null() {
Person actual = null;
Person expected = null;
// THEN
compareRecusively(actual, expected, recursiveComparisonConfiguration);
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
}

@Test
Expand All @@ -79,7 +79,7 @@ public void should_fail_when_actual_is_null_and_expected_is_not() {
Person actual = null;
Person expected = new Person();
// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
// THEN
verify(failures).failure(INFO, shouldNotBeNull());
}
Expand All @@ -90,7 +90,7 @@ public void should_fail_when_actual_is_not_null_and_expected_is() {
Person actual = new Person();
Person expected = null;
// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
// THEN
verify(failures).failure(INFO, shouldBeEqual(actual, null, objects.getComparisonStrategy(), INFO.representation()));
}
Expand All @@ -101,7 +101,7 @@ public void should_fail_when_actual_is_not_null_and_expected_is() {
public void should_pass_for_objects_with_the_same_data_when_using_the_default_recursive_comparison(Object actual,
Object expected,
String testDescription) {
compareRecusively(actual, expected, recursiveComparisonConfiguration);
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
}

@SuppressWarnings("unused")
Expand Down Expand Up @@ -132,7 +132,7 @@ public void should_pass_for_objects_with_the_same_data_when_all_null_fields_are_
// GIVEN
recursiveComparisonConfiguration.setIgnoreAllActualNullFields(true);
// THEN
compareRecusively(actual, expected, recursiveComparisonConfiguration);
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
}

@Test
Expand All @@ -146,7 +146,7 @@ public void should_fail_when_actual_differs_from_expected_even_when_all_null_fie
expected.home.address.number = 2;
recursiveComparisonConfiguration.setIgnoreAllActualNullFields(true);
// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));
// THEN
ComparisonDifference comparisonDifference = new ComparisonDifference(list("home.address.number"), 1, 2);
verifyShouldBeEqualByComparingFieldByFieldRecursivelyCall(actual, expected, comparisonDifference);
Expand Down Expand Up @@ -213,7 +213,7 @@ public void should_pass_for_objects_with_the_same_data_when_given_fields_are_ign
// GIVEN
recursiveComparisonConfiguration.ignoreFields(ignoredFields.toArray(new String[0]));
// THEN
compareRecusively(actual, expected, recursiveComparisonConfiguration);
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
}

@SuppressWarnings("unused")
Expand Down Expand Up @@ -281,7 +281,7 @@ public void should_fail_when_actual_differs_from_expected_even_when_some_fields_
recursiveComparisonConfiguration.ignoreFields("name", "home.address.number");

// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));

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

// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));

// THEN
ComparisonDifference dateOfBirthDifference = diff("dateOfBirth", actual.dateOfBirth, expected.dateOfBirth);
Expand Down
Expand Up @@ -44,7 +44,7 @@ public void should_pass_when_comparison_ignores_overridden_equals_methods_by_reg
// GIVEN
recursiveComparisonConfiguration.ignoreOverriddenEqualsByRegexes(regexes.toArray(new String[0]));
// THEN
compareRecusively(actual, expected, recursiveComparisonConfiguration);
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
}

@SuppressWarnings("unused")
Expand Down Expand Up @@ -88,7 +88,7 @@ public void should_fail_when_actual_differs_from_expected_as_some_overridden_equ
recursiveComparisonConfiguration.ignoreOverriddenEqualsByRegexes(".*AlwaysEqualPerson", ".*AlwaysEqualAddress");

// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));

// THEN
ComparisonDifference neighbourNameDifference = diff("neighbour.name", actual.neighbour.name, expected.neighbour.name);
Expand All @@ -110,7 +110,7 @@ public void should_pass_when_comparison_ignores_overridden_equals_methods_by_typ
// GIVEN
recursiveComparisonConfiguration.ignoreOverriddenEqualsForTypes(types.toArray(new Class[0]));
// THEN
compareRecusively(actual, expected, recursiveComparisonConfiguration);
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
}

@SuppressWarnings("unused")
Expand Down Expand Up @@ -152,7 +152,7 @@ public void should_fail_when_actual_differs_from_expected_as_some_overridden_equ
recursiveComparisonConfiguration.ignoreOverriddenEqualsForTypes(AlwaysEqualPerson.class, AlwaysEqualAddress.class);

// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));

// THEN
ComparisonDifference neighbourNameDifference = diff("neighbour.name", actual.neighbour.name, expected.neighbour.name);
Expand All @@ -174,7 +174,7 @@ public void should_pass_when_comparison_ignores_overridden_equals_methods_by_fie
// GIVEN
recursiveComparisonConfiguration.ignoreOverriddenEqualsForFields(fields.toArray(new String[0]));
// THEN
compareRecusively(actual, expected, recursiveComparisonConfiguration);
areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration);
}

@SuppressWarnings("unused")
Expand Down Expand Up @@ -216,7 +216,7 @@ public void should_fail_when_actual_differs_from_expected_as_some_overridden_equ
recursiveComparisonConfiguration.ignoreOverriddenEqualsForFields("neighbour", "neighbour.home.address");

// WHEN
expectAssertionError(() -> compareRecusively(actual, expected, recursiveComparisonConfiguration));
expectAssertionError(() -> areEqualsByRecursiveComparison(actual, expected, recursiveComparisonConfiguration));

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

}

0 comments on commit 6f62ebe

Please sign in to comment.