package com.sishuok.matcher; import org.hamcrest.*; import org.springframework.beans.BeanWrapperImpl; import static org.hamcrest.Condition.matched; import static org.hamcrest.Condition.notMatched; /** * <p>User: Zhang Kaitao * <p>Date: 13-12-29 * <p>Version: 1.0 */ public class HasPropertyWithValue<T> extends TypeSafeDiagnosingMatcher<T> { private final String propertyNames; private final Matcher<Object> valueMatcher; public HasPropertyWithValue(String propertyNames, Matcher<?> valueMatcher) { this.propertyNames = propertyNames; this.valueMatcher = nastyGenericsWorkaround(valueMatcher); } @Override public boolean matchesSafely(T bean, Description mismatch) { return withPropertyValue(bean, mismatch) .matching(valueMatcher, "property '" + propertyNames + "' "); } @Override public void describeTo(Description description) { description.appendText("hasProperty(").appendValue(propertyNames).appendText(", ") .appendDescriptionOf(valueMatcher).appendText(")"); } private Condition<Object> withPropertyValue(T bean, Description mismatch) { try { BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean); Object property = beanWrapper.getPropertyValue(propertyNames); if (property == null) { mismatch.appendText("No property \"" + propertyNames + "\""); return notMatched(); } return matched(property, mismatch); } catch (Exception e) { mismatch.appendText(e.getMessage()); return notMatched(); } } @SuppressWarnings("unchecked") private static Matcher<Object> nastyGenericsWorkaround(Matcher<?> valueMatcher) { return (Matcher<Object>) valueMatcher; } @Factory public static <T> Matcher<T> hasProperty(String propertyName, Matcher<?> valueMatcher) { return new HasPropertyWithValue<T>(propertyName, valueMatcher); } }