Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ignorable fields to HasEqualValues #351

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions hamcrest/src/main/java/org/hamcrest/Matchers.java
Original file line number Diff line number Diff line change
Expand Up @@ -2108,6 +2108,24 @@ public static <B> Matcher<B> samePropertyValuesAs(B expectedBean, String... igno
return org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs(expectedBean, ignoredProperties);
}

/**
* Creates a matcher that matches when the examined object has values for all of
* its fields that are equal to the corresponding values of the
* specified object. If any fields are marked as ignored, they will be dropped from
* both the expected and actual object.
* For example:
* <pre>assertThat(myObject, hasEqualValues(myExpectedObject))</pre>
* <pre>assertThat(myObject, hasEqualValues(myExpectedObject), "age", "height")</pre>
*
* @param expectedObject
* the object against which examined objects are compared
* @param ignoredFields
* do not check any of these named fields.
*/
public static <B> Matcher<B> hasEqualValues(B expectedObject, String... ignoredFields) {
return org.hamcrest.object.HasEqualValues.hasEqualValues(expectedObject, ignoredFields);
}

/**
* Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the
* specified <code>xPath</code> that satisfies the specified <code>valueMatcher</code>.
Expand Down
33 changes: 30 additions & 3 deletions hamcrest/src/main/java/org/hamcrest/object/HasEqualValues.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static java.lang.String.format;
import static java.util.Arrays.asList;

public class HasEqualValues<T> extends TypeSafeDiagnosingMatcher<T> {

private final T expectedObject;
private final List<FieldMatcher> fieldMatchers;

public HasEqualValues(T expectedObject) {
this(expectedObject, Collections.<String>emptySet());
}

public HasEqualValues(T expectedObject, Set<String> ignored) {
super(expectedObject.getClass());
this.expectedObject = expectedObject;
this.fieldMatchers = fieldMatchers(expectedObject);
this.fieldMatchers = fieldMatchers(expectedObject, ignored);
}

@Override
Expand Down Expand Up @@ -67,10 +75,12 @@ public void describeTo(Description description) {
}
}

private static List<FieldMatcher> fieldMatchers(Object expectedObject) {
private static List<FieldMatcher> fieldMatchers(Object expectedObject, Set<String> ignored) {
final List<FieldMatcher> result = new ArrayList<>();
for (Field field : expectedObject.getClass().getFields()) {
result.add(new FieldMatcher(field, expectedObject));
if (!ignored.contains(field.getName())) {
result.add(new FieldMatcher(field, expectedObject));
}
}
return result;
}
Expand All @@ -83,4 +93,21 @@ private static Object uncheckedGet(Field field, Object object) {
}
}

/**
* Creates a matcher that matches when the examined object has values for all of
* its fields that are equal to the corresponding values of the
* specified object. If any fields are marked as ignored, they will be dropped from
* both the expected and actual object.
* For example:
* <pre>assertThat(myObject, hasEqualValues(myExpectedObject))</pre>
* <pre>assertThat(myObject, hasEqualValues(myExpectedObject), "age", "height")</pre>
*
* @param expectedObject
* the object against which examined objects are compared
* @param ignoredFields
* do not check any of these named fields.
*/
public static <B> Matcher<B> hasEqualValues(B expectedObject, String... ignoredFields) {
return new HasEqualValues<>(expectedObject, new HashSet<>(asList(ignoredFields)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import org.hamcrest.AbstractMatcherTest;
import org.hamcrest.Matcher;

import java.util.Collections;

@SuppressWarnings("WeakerAccess")
public class HasEqualsValuesTest extends AbstractMatcherTest {

private static final WithPublicFields WITH_PUBLIC_FIELDS = new WithPublicFields('x', 666, "a string");
private static final HasEqualValues<WithPublicFields> WITH_PUBLIC_FIELDS_MATCHER = new HasEqualValues<>(WITH_PUBLIC_FIELDS);
private static final WithPublicFields WITH_PUBLIC_FIELDS = new WithPublicFields('x', 666, "a string", false);
private static final HasEqualValues<WithPublicFields> WITH_PUBLIC_FIELDS_MATCHER = new HasEqualValues<>(WITH_PUBLIC_FIELDS, Collections.singleton("ignorable"));

@Override
protected Matcher<?> createMatcher() {
Expand All @@ -21,29 +23,31 @@ public void test_describes_itself() {
}

public void test_matches_equivalent_object() {
assertMatches(WITH_PUBLIC_FIELDS_MATCHER, new WithPublicFields('x', 666, "a string"));
assertMatches(WITH_PUBLIC_FIELDS_MATCHER, new WithPublicFields('x', 666, "a string", true));
}

public void test_mismatches_on_first_field_inequality() {
assertMismatchDescription(
"'s' was \"different\"",
WITH_PUBLIC_FIELDS_MATCHER, new WithPublicFields('x', 666, "different"));
WITH_PUBLIC_FIELDS_MATCHER, new WithPublicFields('x', 666, "different", true));
}

public void test_mismatches_on_inherited_field() {
assertMismatchDescription(
"'c' was \"y\"",
WITH_PUBLIC_FIELDS_MATCHER, new WithPublicFields('y', 666, "a string"));
WITH_PUBLIC_FIELDS_MATCHER, new WithPublicFields('y', 666, "a string", true));
}

public static class WithPublicFields extends Parent {
public final int i;
public final String s;
public final boolean ignorable;

public WithPublicFields(char c, int i, String s) {
public WithPublicFields(char c, int i, String s, boolean ignorable) {
super(c);
this.i = i;
this.s = s;
this.ignorable = ignorable;
}
}

Expand Down