Class RecursiveComparisonDifferenceCalculator
- java.lang.Object
-
- org.assertj.core.api.recursive.comparison.RecursiveComparisonDifferenceCalculator
-
public class RecursiveComparisonDifferenceCalculator extends Object
Based onDeepDifference
but takes aRecursiveComparisonConfiguration
,DeepDifference
being itself based on the deep equals implementation of https://github.com/jdereg/java-util- Author:
- John DeRegnaucourt ([email protected]), Pascal Schumacher
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
RecursiveComparisonDifferenceCalculator.ComparisonState
-
Field Summary
Fields Modifier and Type Field Description private static String
ACTUAL_NOT_ORDERED_COLLECTION
private static Map<Class<?>,Boolean>
customEquals
private static Map<Class<?>,Boolean>
customHash
private static String
DIFFERENT_ACTUAL_AND_EXPECTED_FIELD_TYPES
private static String
DIFFERENT_SIZE_ERROR
private static String
MISSING_FIELDS
private static String
STRICT_TYPE_ERROR
private static String
VALUE_FIELD_NAME
-
Constructor Summary
Constructors Constructor Description RecursiveComparisonDifferenceCalculator()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description private static void
compareArrays(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
private static void
compareIterables(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
private static void
compareOptional(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
private static void
compareOrderedCollections(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
private static <K,V>
voidcompareSortedMap(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
private static void
compareUnorderedMap(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
(package private) static int
deepHashCode(Object obj)
Get a deterministic hashCode (int) value for an Object, regardless of when it was created or where it was loaded into memory.private static String
describeOrderedCollectionTypes()
private static List<ComparisonDifference>
determineDifferences(Object actual, Object expected, List<String> parentPath, Set<DualValue> visited, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
List<ComparisonDifference>
determineDifferences(Object actual, Object expected, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
Compare two objects for differences by doing a 'deep' comparison.private static String
differentTypeErrorMessage(DualValue dualValue, String actualTypeDescription)
private static ComparisonDifference
expectedAndActualTypeDifference(Object actual, Object expected)
private static boolean
expectedTypeIsNotSubtypeOfActualType(Object actual, Object expected)
private static boolean
expectedTypeIsNotSubtypeOfActualType(DualValue dualField)
private static Set<String>
getFieldsNames(Class<?> clazz)
private static Set<String>
getNonIgnoredFieldNames(Class<?> actualClass, List<String> parentPath, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
private static boolean
hasCustomComparator(DualValue dualValue, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
(package private) static boolean
hasCustomEquals(Class<?> c)
Determine if the passed in class has a non-Object.equals() method.(package private) static boolean
hasCustomHashCode(Class<?> c)
Determine if the passed in class has a non-Object.hashCode() method.private static boolean
isContainerType(Object o)
private static boolean
propertyOrFieldValuesAreEqual(DualValue dualValue, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
-
-
-
Field Detail
-
DIFFERENT_ACTUAL_AND_EXPECTED_FIELD_TYPES
private static final String DIFFERENT_ACTUAL_AND_EXPECTED_FIELD_TYPES
- See Also:
- Constant Field Values
-
ACTUAL_NOT_ORDERED_COLLECTION
private static final String ACTUAL_NOT_ORDERED_COLLECTION
-
VALUE_FIELD_NAME
private static final String VALUE_FIELD_NAME
- See Also:
- Constant Field Values
-
STRICT_TYPE_ERROR
private static final String STRICT_TYPE_ERROR
- See Also:
- Constant Field Values
-
DIFFERENT_SIZE_ERROR
private static final String DIFFERENT_SIZE_ERROR
- See Also:
- Constant Field Values
-
MISSING_FIELDS
private static final String MISSING_FIELDS
- See Also:
- Constant Field Values
-
-
Method Detail
-
determineDifferences
public List<ComparisonDifference> determineDifferences(Object actual, Object expected, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
Compare two objects for differences by doing a 'deep' comparison. This will traverse the Object graph and perform either a field-by-field comparison on each object (if not .equals() method has been overridden from Object), or it will call the customized .equals() method if it exists.This method handles cycles correctly, for example A->B->C->A. Suppose a and a' are two separate instances of the A with the same values for all fields on A, B, and C. Then a.deepEquals(a') will return an empty list. It uses cycle detection storing visited objects in a Set to prevent endless loops.
- Parameters:
actual
- Object one to compareexpected
- Object two to comparerecursiveComparisonConfiguration
- the recursive comparison configuration- Returns:
- the list of differences found or an empty list if objects are equivalent. Equivalent means that all field values of both subgraphs are the same, either at the field level or via the respectively encountered overridden .equals() methods during traversal.
-
determineDifferences
private static List<ComparisonDifference> determineDifferences(Object actual, Object expected, List<String> parentPath, Set<DualValue> visited, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
-
hasCustomComparator
private static boolean hasCustomComparator(DualValue dualValue, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
-
getNonIgnoredFieldNames
private static Set<String> getNonIgnoredFieldNames(Class<?> actualClass, List<String> parentPath, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
-
isContainerType
private static boolean isContainerType(Object o)
-
compareArrays
private static void compareArrays(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
-
compareOrderedCollections
private static void compareOrderedCollections(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
-
differentTypeErrorMessage
private static String differentTypeErrorMessage(DualValue dualValue, String actualTypeDescription)
-
compareIterables
private static void compareIterables(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
-
compareSortedMap
private static <K,V> void compareSortedMap(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
-
compareUnorderedMap
private static void compareUnorderedMap(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
-
compareOptional
private static void compareOptional(DualValue dualValue, RecursiveComparisonDifferenceCalculator.ComparisonState comparisonState)
-
hasCustomEquals
static boolean hasCustomEquals(Class<?> c)
Determine if the passed in class has a non-Object.equals() method. This method caches its results in static ConcurrentHashMap to benefit execution performance.- Parameters:
c
- Class to check.- Returns:
- true, if the passed in Class has a .equals() method somewhere between itself and just below Object in it's inheritance.
-
deepHashCode
static int deepHashCode(Object obj)
Get a deterministic hashCode (int) value for an Object, regardless of when it was created or where it was loaded into memory. The problem with java.lang.Object.hashCode() is that it essentially relies on memory location of an object (what identity it was assigned), whereas this method will produce the same hashCode for any object graph, regardless of how many times it is created.
This method will handle cycles correctly (A->B->C->A). In this case, Starting with object A, B, or C would yield the same hashCode. If an object encountered (root, subobject, etc.) has a hashCode() method on it (that is not Object.hashCode()), that hashCode() method will be called and it will stop traversal on that branch.- Parameters:
obj
- Object who hashCode is desired.- Returns:
- the 'deep' hashCode value for the passed in object.
-
hasCustomHashCode
static boolean hasCustomHashCode(Class<?> c)
Determine if the passed in class has a non-Object.hashCode() method. This method caches its results in static ConcurrentHashMap to benefit execution performance.- Parameters:
c
- Class to check.- Returns:
- true, if the passed in Class has a .hashCode() method somewhere between itself and just below Object in it's inheritance.
-
propertyOrFieldValuesAreEqual
private static boolean propertyOrFieldValuesAreEqual(DualValue dualValue, RecursiveComparisonConfiguration recursiveComparisonConfiguration)
-
expectedAndActualTypeDifference
private static ComparisonDifference expectedAndActualTypeDifference(Object actual, Object expected)
-
expectedTypeIsNotSubtypeOfActualType
private static boolean expectedTypeIsNotSubtypeOfActualType(DualValue dualField)
-
expectedTypeIsNotSubtypeOfActualType
private static boolean expectedTypeIsNotSubtypeOfActualType(Object actual, Object expected)
-
describeOrderedCollectionTypes
private static String describeOrderedCollectionTypes()
-
-