org.hamcrest.beans.SamePropertyValuesAs Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hamcrest Show documentation
Show all versions of hamcrest Show documentation
Core API and libraries of hamcrest matcher framework.
The newest version!
package org.hamcrest.beans;
import org.hamcrest.Description;
import org.hamcrest.DiagnosingMatcher;
import org.hamcrest.Matcher;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;
import static java.util.Arrays.asList;
import static org.hamcrest.beans.PropertyUtil.NO_ARGUMENTS;
import static org.hamcrest.beans.PropertyUtil.propertyDescriptorsFor;
import static org.hamcrest.core.IsEqual.equalTo;
public class SamePropertyValuesAs extends DiagnosingMatcher {
private final T expectedBean;
private final Set propertyNames;
private final List propertyMatchers;
private final List ignoredFields;
@SuppressWarnings("WeakerAccess")
public SamePropertyValuesAs(T expectedBean, List ignoredProperties) {
PropertyDescriptor[] descriptors = propertyDescriptorsFor(expectedBean, Object.class);
this.expectedBean = expectedBean;
this.ignoredFields = ignoredProperties;
this.propertyNames = propertyNamesFrom(descriptors, ignoredProperties);
this.propertyMatchers = propertyMatchersFor(expectedBean, descriptors, ignoredProperties);
}
@Override
protected boolean matches(Object actual, Description mismatch) {
return isNotNull(actual, mismatch)
&& isCompatibleType(actual, mismatch)
&& hasNoExtraProperties(actual, mismatch)
&& hasMatchingValues(actual, mismatch);
}
@Override
public void describeTo(Description description) {
description.appendText("same property values as " + expectedBean.getClass().getSimpleName())
.appendList(" [", ", ", "]", propertyMatchers);
if (! ignoredFields.isEmpty()) {
description.appendText(" ignoring ")
.appendValueList("[", ", ", "]", ignoredFields);
}
}
private boolean isCompatibleType(Object actual, Description mismatchDescription) {
if (expectedBean.getClass().isAssignableFrom(actual.getClass())) {
return true;
}
mismatchDescription.appendText("is incompatible type: " + actual.getClass().getSimpleName());
return false;
}
private boolean hasNoExtraProperties(Object actual, Description mismatchDescription) {
Set actualPropertyNames = propertyNamesFrom(propertyDescriptorsFor(actual, Object.class), ignoredFields);
actualPropertyNames.removeAll(propertyNames);
if (!actualPropertyNames.isEmpty()) {
mismatchDescription.appendText("has extra properties called " + actualPropertyNames);
return false;
}
return true;
}
private boolean hasMatchingValues(Object actual, Description mismatchDescription) {
for (PropertyMatcher propertyMatcher : propertyMatchers) {
if (!propertyMatcher.matches(actual)) {
propertyMatcher.describeMismatch(actual, mismatchDescription);
return false;
}
}
return true;
}
private static List propertyMatchersFor(T bean, PropertyDescriptor[] descriptors, List ignoredFields) {
List result = new ArrayList<>(descriptors.length);
for (PropertyDescriptor propertyDescriptor : descriptors) {
if (isIgnored(ignoredFields, propertyDescriptor)) {
result.add(new PropertyMatcher(propertyDescriptor, bean));
}
}
return result;
}
private static Set propertyNamesFrom(PropertyDescriptor[] descriptors, List ignoredFields) {
HashSet result = new HashSet<>();
for (PropertyDescriptor propertyDescriptor : descriptors) {
if (isIgnored(ignoredFields, propertyDescriptor)) {
result.add(propertyDescriptor.getDisplayName());
}
}
return result;
}
private static boolean isIgnored(List ignoredFields, PropertyDescriptor propertyDescriptor) {
return ! ignoredFields.contains(propertyDescriptor.getDisplayName());
}
@SuppressWarnings("WeakerAccess")
private static class PropertyMatcher extends DiagnosingMatcher