com.atlassian.hamcrest
Class DeepIsEqual<T>

java.lang.Object
  extended by org.hamcrest.BaseMatcher<T>
      extended by org.hamcrest.DiagnosingMatcher<T>
          extended by com.atlassian.hamcrest.DeepIsEqual<T>
All Implemented Interfaces:
org.hamcrest.Matcher<T>, org.hamcrest.SelfDescribing

public class DeepIsEqual<T>
extends org.hamcrest.DiagnosingMatcher<T>

A matcher that does a deep equals comparison of objects using reflection. This allows testers to compare arbitrary objects, whether they implement the Object.equals(java.lang.Object) method or not. It only tries to match 2 objects of the exact same type. If one type is a sub-type of another, the match will fail. The actual and expected objects are compared by reflectively finding the types' declared, non-static, non-transient fields and the declared, non-static, non-transient fields of its parents. There is a core set of matchers used to compare the values of primitive field types and arrays. If the field is an array, then each element of the array is compared.

A tester can also provide a way to create custom Matchers for field types. To provide custom matchers for certain field types, you pass in a Map that indicates the type of the field you want to use a custom matcher for and how to create the custom matcher. Hamcrest Matchers are used to indicate the field type, so you can use equalTo to match types exactly or create your own to match subclasses, etc. Once a matching type is found, a Matcher is created using the MatcherFactory.

As an example of how this works, you can register a MatcherFactory which will be used when the field type is a java.security.Key. For this example, we really want a type matcher that checks if the type of the value implements the Key interface, because it will never match exactly. To do that, we'll use the ClassMatchers.isAssignableTo(Class) matcher and we'll say we want keys to match exactly using the in-built MatcherFactories.isEqual() MatcherFactory.


     Map>, MatcherFactory> matcherFactories = new HashMap>, MatcherFactory>();
     matcherFactories.put(isAssignableTo(Key.class), isEqual());
     assertThat(actualValue, is(deeplyEqualTo(expectedValue, matcherFactories)));
 
Because that isn't exactly the clearest code, it is highly recommended that you create utility methods that encapsulate the creation of the the MatcherFactory maps and registration of them to make your tests easier to read.

Note: There is currently no support for cyclic object graphs and no effort made to detect them. If there is a cycle in your object graph it will cause a StackOverflowError. If you have cycles in your object graph you can overcome this limitation by providing a custom matcher.


Method Summary
static
<T> org.hamcrest.Matcher<? super T>
deeplyEqualTo(T operand)
          Returns a Matcher which compares two objects reflectively.
static
<T> org.hamcrest.Matcher<? super T>
deeplyEqualTo(T operand, java.util.Map<org.hamcrest.Matcher<java.lang.Class<?>>,MatcherFactory> extraMatcherFactories)
          Returns a Matcher which compares 2 objects reflectively and uses the custom MatcherFactorys to determine how to match certain types of fields.
 void describeTo(org.hamcrest.Description description)
           
protected  boolean matches(java.lang.Object actual, org.hamcrest.Description mismatchDescription)
          Checks that the type of actual matches the type of the expected value and then that the composite object values are equal.
 
Methods inherited from class org.hamcrest.DiagnosingMatcher
describeMismatch, matches
 
Methods inherited from class org.hamcrest.BaseMatcher
_dont_implement_Matcher___instead_extend_BaseMatcher_, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Method Detail

matches

protected boolean matches(java.lang.Object actual,
                          org.hamcrest.Description mismatchDescription)
Checks that the type of actual matches the type of the expected value and then that the composite object values are equal.

Specified by:
matches in class org.hamcrest.DiagnosingMatcher<T>

describeTo

public void describeTo(org.hamcrest.Description description)

deeplyEqualTo

public static <T> org.hamcrest.Matcher<? super T> deeplyEqualTo(T operand)
Returns a Matcher which compares two objects reflectively.

Type Parameters:
T - type of the objects to compare
Parameters:
operand - the expected value
Returns:
Matcher which compares two objects reflectively

deeplyEqualTo

public static <T> org.hamcrest.Matcher<? super T> deeplyEqualTo(T operand,
                                                                java.util.Map<org.hamcrest.Matcher<java.lang.Class<?>>,MatcherFactory> extraMatcherFactories)
Returns a Matcher which compares 2 objects reflectively and uses the custom MatcherFactorys to determine how to match certain types of fields.

Type Parameters:
T - type of the objects to compare
Parameters:
operand - the expected value
extraMatcherFactories - MatcherFactorys to use for the fields with types matching the key Matcher
Returns:
Matcher which compares 2 objects reflectively
See Also:
DeepIsEqual


Copyright © 2009 Atlassian. All Rights Reserved.