Skip to content

Commit 359c3ca

Browse files
author
smgfreeman
committed
improved mismatch reporting in HasPropertyWithValue
1 parent e4c724e commit 359c3ca

File tree

2 files changed

+41
-36
lines changed

2 files changed

+41
-36
lines changed

hamcrest-library/src/main/java/org/hamcrest/beans/HasPropertyWithValue.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,26 +68,25 @@
6868
*/
6969
public class HasPropertyWithValue<T> extends TypeSafeDiagnosingMatcher<T> {
7070
private final String propertyName;
71-
private final Matcher<?> value;
71+
private final Matcher<?> valueMatcher;
7272

73-
public HasPropertyWithValue(String propertyName, Matcher<?> value) {
73+
public HasPropertyWithValue(String propertyName, Matcher<?> valueMatcher) {
7474
this.propertyName = propertyName;
75-
this.value = value;
75+
this.valueMatcher = valueMatcher;
7676
}
7777

7878
@Override
79-
public boolean matchesSafely(T argument, Description mismatchDescription) {
79+
public boolean matchesSafely(T bean, Description mismatchDescription) {
8080
try {
81-
Method readMethod = getReadMethod(argument);
81+
Method readMethod = findReadMethod(bean, mismatchDescription);
8282
if (readMethod == null) {
83-
mismatchDescription.appendText("missing.");
8483
return false;
8584
}
86-
Object propertyValue = readMethod.invoke(argument, NO_ARGUMENTS);
87-
boolean valueMatches = value.matches(propertyValue);
85+
Object propertyValue = readMethod.invoke(bean, NO_ARGUMENTS);
86+
boolean valueMatches = valueMatcher.matches(propertyValue);
8887
if (!valueMatches) {
89-
value.describeMismatch(propertyValue, mismatchDescription);
90-
mismatchDescription.appendText(".");
88+
mismatchDescription.appendText("property \"" + propertyName + "\" ");
89+
valueMatcher.describeMismatch(propertyValue, mismatchDescription);
9190
}
9291
return valueMatches;
9392
} catch (IllegalArgumentException e) {
@@ -99,16 +98,24 @@ public boolean matchesSafely(T argument, Description mismatchDescription) {
9998
}
10099
}
101100

102-
private Method getReadMethod(Object argument) throws IllegalArgumentException {
101+
private Method findReadMethod(Object argument, Description mismatchDescription) throws IllegalArgumentException {
103102
PropertyDescriptor property = PropertyUtil.getPropertyDescriptor(propertyName, argument);
104-
return property == null ? null : property.getReadMethod();
103+
if (null == property) {
104+
mismatchDescription.appendText("No property \"" + propertyName + "\"");
105+
return null;
106+
}
107+
Method readMethod = property.getReadMethod();
108+
if (null == readMethod) {
109+
mismatchDescription.appendText("property \"" + propertyName + "\" is not readable");
110+
}
111+
return readMethod;
105112
}
106113

107114
public void describeTo(Description description) {
108115
description.appendText("hasProperty(");
109116
description.appendValue(propertyName);
110117
description.appendText(", ");
111-
description.appendDescriptionOf(value);
118+
description.appendDescriptionOf(valueMatcher);
112119
description.appendText(")");
113120
}
114121

hamcrest-unit-test/src/main/java/org/hamcrest/beans/HasPropertyWithValueTest.java

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
77
import static org.hamcrest.core.IsAnything.anything;
88
import static org.hamcrest.core.IsEqual.equalTo;
9-
import static org.hamcrest.core.IsNot.not;
109

1110
import java.beans.IntrospectionException;
1211
import java.beans.PropertyDescriptor;
@@ -38,45 +37,43 @@ protected Matcher<?> createMatcher() {
3837
}
3938

4039
public void testMatchesInfolessBeanWithMatchedNamedProperty() {
41-
assertThat(shouldMatch, hasProperty("property", equalTo("is expected")));
42-
assertThat(shouldNotMatch, not(hasProperty("property", equalTo("is expected"))));
40+
assertMatches("with property", hasProperty("property", equalTo("is expected")), shouldMatch);
41+
assertMismatchDescription("property \"property\" was \"not expected\"",
42+
hasProperty("property", equalTo("is expected")), shouldNotMatch);
4343
}
4444

4545
public void testMatchesBeanWithInfoWithMatchedNamedProperty() {
46-
assertThat(beanWithInfo, hasProperty("property", equalTo("with info")));
46+
assertMatches("with bean info", hasProperty("property", equalTo("with info")), beanWithInfo);
47+
assertMismatchDescription("property \"property\" was \"with info\"",
48+
hasProperty("property", equalTo("without info")), beanWithInfo);
4749
}
4850

4951
public void testDoesNotMatchInfolessBeanWithoutMatchedNamedProperty() {
50-
assertThat(shouldNotMatch, not(hasProperty("nonExistentProperty", anything())));
51-
}
52+
assertMismatchDescription("No property \"nonExistentProperty\"",
53+
hasProperty("nonExistentProperty", anything()), shouldNotMatch);
54+
}
5255

5356
public void testDoesNotMatchWriteOnlyProperty() {
54-
assertThat(shouldNotMatch,
55-
not(hasProperty("writeOnlyProperty", anything())));
57+
assertMismatchDescription("property \"writeOnlyProperty\" is not readable",
58+
hasProperty("writeOnlyProperty", anything()), shouldNotMatch);
5659
}
5760

5861
public void testDescribeTo() {
59-
Matcher<?> matcher = equalTo(true);
60-
61-
assertDescription("hasProperty(\"property\", "
62-
+ StringDescription.asString(matcher) + ")", hasProperty("property", matcher));
62+
assertDescription("hasProperty(\"property\", <true>)", hasProperty("property", equalTo(true)));
6363
}
6464

65+
public void testMatchesPropertyAndValue() {
66+
assertMatches("property with value", hasProperty( "property", anything()), beanWithInfo);
67+
}
68+
6569
public void testDoesNotWriteMismatchIfPropertyMatches() {
66-
Matcher<Object> matcher = hasProperty( "property", anything());
67-
assertTrue("Precondtion: Matcher should match item.", matcher.matches(beanWithInfo));
6870
Description description = new StringDescription();
69-
matcher.describeMismatch(beanWithInfo, description);
71+
hasProperty( "property", anything()).describeMismatch(beanWithInfo, description);
7072
assertEquals("Expected mismatch description", "", description.toString());
7173
}
7274

7375
public void testDescribesMissingPropertyMismatch() {
74-
assertMismatchDescription("missing.", hasProperty( "honk", anything()), shouldNotMatch);
75-
}
76-
77-
public void testDescribesMismatchingPropertyValueMismatch() {
78-
assertMismatchDescription("was \"not expected\".",
79-
hasProperty("property", equalTo("foo")), shouldNotMatch);
76+
assertMismatchDescription("No property \"honk\"", hasProperty( "honk", anything()), shouldNotMatch);
8077
}
8178

8279
public void testCanAccessAnAnonymousInnerClass() {
@@ -133,8 +130,9 @@ public static class BeanWithInfoBeanInfo extends SimpleBeanInfo {
133130
@Override
134131
public PropertyDescriptor[] getPropertyDescriptors() {
135132
try {
136-
return new PropertyDescriptor[] { new PropertyDescriptor("property",
137-
BeanWithInfo.class, "property", null) };
133+
return new PropertyDescriptor[] {
134+
new PropertyDescriptor("property", BeanWithInfo.class, "property", null)
135+
};
138136
} catch (IntrospectionException e) {
139137
throw new RuntimeException("Introspection exception: " + e.getMessage());
140138
}

0 commit comments

Comments
 (0)