我在大多数测试中都使用了hamcrest,但遇到了一个问题,它无法在对象图中测试一个级别的属性。我的测试用例的剪辑在下面
final List<Foo> foos= fooRepository.findAll(spec);
assertThat(results, is(notNullValue()));
assertThat(results, hasItem(hasProperty("id.fooID1", equalTo("FOOID1"))));
所以在这里我要检查是否在foos列表中我有一个属性id.fooID1 equla到FOOID1。这是我向下一级检查我的嵌套属性。这目前无法在hamcrest工作,我得到以下错误。
java.lang.AssertionError:
Expected: a collection containing hasProperty("id.fooID1", "FOOID1")
but: No property "id.fooID1"
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:956)
at org.junit.Assert.assertThat(Assert.java:923)
有关此问题的任何帮助或解决方法。
答案 0 :(得分:18)
您可以嵌套hasProperty
来电:
assertThat(results, hasItem(hasProperty("id", hasProperty("fooID1", equalTo("FOOID1")))));
对于更深的嵌套,这可能有点笨拙。
答案 1 :(得分:4)
我已经通过这个简单的实用方法获得了您期望的结果:
private static <T> Matcher<T> hasGraph(String graphPath, Matcher<T> matcher) {
List<String> properties = Arrays.asList(graphPath.split("\\."));
ListIterator<String> iterator =
properties.listIterator(properties.size());
Matcher<T> ret = matcher;
while (iterator.hasPrevious()) {
ret = hasProperty(iterator.previous(), ret);
}
return ret;
}
我可以在这样的断言中使用:
assertThat(bean, hasGraph("beanProperty.subProperty.subSubProperty", notNullValue()));
检查这是否有任何帮助
答案 2 :(得分:2)
我没有找到问题的API解决方案,但是在1.3 hamcrest的源代码中发现HasPropertyWithValue匹配器实际上没有深入到嵌套属性中。
我已经制作了一个糟糕的解决方案(请注意,找不到的消息不能正常工作):
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");
}
}
非常肯定Hamcrest的人会比我的更好,但我认为这段代码对你来说已经足够了。