I did not find an API solution for your problem, but I found in source 1.3 hamcrest that the HasPropertyWithValue helper does not really immerse itself in nested properties.
I made a lousy decision (note that messages when they are not found do not work properly):
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.hamcrest.beans.PropertyUtil;
public class NestedPropertyMatcher<T> extends TypeSafeDiagnosingMatcher<T>{
private final String[] props;
private final String path;
private final Matcher<?> valueMatcher;
@Override
public boolean matchesSafely(T bean, Description mismatch) {
if (props.length == 1) {
return org.hamcrest.beans.HasPropertyWithValue.hasProperty(props[props.length - 1], valueMatcher).matches(bean);
} else {
Object aux = bean;
for (int i = 0; i < props.length - 1; i++) {
if (!org.hamcrest.beans.HasProperty.hasProperty(props[i]).matches(aux)) {
return false;
} else {
PropertyDescriptor pd = PropertyUtil.getPropertyDescriptor(props[i], aux);
try {
aux = pd.getReadMethod().invoke(aux);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
mismatch.appendText("Exception while trying to access property value: " + e.getLocalizedMessage());
return false;
}
}
}
return org.hamcrest.beans.HasPropertyWithValue.hasProperty(props[props.length - 1], valueMatcher).matches(aux);
}
}
private NestedPropertyMatcher(String path, String[] propertiesTokens, Matcher<?> valueMatcher) {
this.path = path;
this.props = propertiesTokens;
this.valueMatcher = valueMatcher;
}
public static <T> Matcher<T> hasPathProperty(String propertyPath, Matcher<?> valueMatcher) {
String[] props = propertyPath.split("\\.");
return new NestedPropertyMatcher<T>(propertyPath, props, valueMatcher);
}
@Override
public void describeTo(Description description) {
description.appendText("hasProperty(").appendValue(path).appendText(", ").appendDescriptionOf(valueMatcher).appendText(") did not found property");
}
}
I'm pretty sure that people working with hamcrest will do a better job than mine, but I think this code will be enough for you.
source
share