HasEqualValues.java
package org.hamcrest.object;
import org.hamcrest.Description;
import org.hamcrest.DiagnosingMatcher;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.hamcrest.core.IsEqual;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import static java.lang.String.format;
public class HasEqualValues<T> extends TypeSafeDiagnosingMatcher<T> {
private final T expectedObject;
private final List<FieldMatcher> fieldMatchers;
public HasEqualValues(T expectedObject) {
super(expectedObject.getClass());
this.expectedObject = expectedObject;
this.fieldMatchers = fieldMatchers(expectedObject);
}
@Override
protected boolean matchesSafely(T item, Description mismatch) {
for (FieldMatcher fieldMatcher : fieldMatchers) {
if (!fieldMatcher.matches(item, mismatch)) {
return false;
}
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(expectedObject.getClass().getSimpleName())
.appendText(" has values ")
.appendList("[", ", ", "]", fieldMatchers);
}
private static class FieldMatcher extends DiagnosingMatcher<Object> {
private final Field field;
private final Matcher<Object> matcher;
public FieldMatcher(Field field, Object expectedObject) {
this.field = field;
this.matcher = IsEqual.equalTo(uncheckedGet(field, expectedObject));
}
@Override
protected boolean matches(Object item, Description mismatch) {
final Object actual = uncheckedGet(field, item);
if (!matcher.matches(actual)) {
mismatch.appendText("'").appendText(field.getName()).appendText("' ");
matcher.describeMismatch(actual, mismatch);
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(field.getName())
.appendText(": ")
.appendDescriptionOf(matcher);
}
}
private static List<FieldMatcher> fieldMatchers(Object expectedObject) {
final List<FieldMatcher> result = new ArrayList<>();
for (Field field : expectedObject.getClass().getFields()) {
result.add(new FieldMatcher(field, expectedObject));
}
return result;
}
private static Object uncheckedGet(Field field, Object object) {
try {
return field.get(object);
} catch (Exception e) {
throw new AssertionError(format("IllegalAccess, reading field '%s' from %s", field.getName(), object));
}
}
}