5
5
import org .hamcrest .Matcher ;
6
6
import org .hamcrest .TypeSafeDiagnosingMatcher ;
7
7
8
+ import java .beans .FeatureDescriptor ;
9
+ import java .beans .MethodDescriptor ;
8
10
import java .beans .PropertyDescriptor ;
9
11
import java .lang .reflect .InvocationTargetException ;
10
12
import java .lang .reflect .Method ;
26
28
* <h2>Example Usage</h2>
27
29
* Consider the situation where we have a class representing a person, which
28
30
* follows the basic JavaBean convention of having get() and possibly set()
29
- * methods for it's properties:
31
+ * methods for its properties:
30
32
* <pre>{@code public class Person {
31
33
* private String name;
32
34
* public Person(String person) {
69
71
*/
70
72
public class HasPropertyWithValue <T > extends TypeSafeDiagnosingMatcher <T > {
71
73
72
- private static final Condition .Step <PropertyDescriptor , Method > WITH_READ_METHOD = withReadMethod ();
74
+ private static final Condition .Step <FeatureDescriptor , Method > WITH_READ_METHOD = withReadMethod ();
73
75
private final String propertyName ;
74
76
private final Matcher <Object > valueMatcher ;
75
77
private final String messageFormat ;
@@ -111,8 +113,11 @@ public void describeTo(Description description) {
111
113
.appendDescriptionOf (valueMatcher ).appendText (")" );
112
114
}
113
115
114
- private Condition <PropertyDescriptor > propertyOn (T bean , Description mismatch ) {
115
- PropertyDescriptor property = PropertyUtil .getPropertyDescriptor (propertyName , bean );
116
+ private Condition <FeatureDescriptor > propertyOn (T bean , Description mismatch ) {
117
+ FeatureDescriptor property = PropertyUtil .getPropertyDescriptor (propertyName , bean );
118
+ if (property == null ) {
119
+ property = PropertyUtil .getMethodDescriptor (propertyName , bean );
120
+ }
116
121
if (property == null ) {
117
122
mismatch .appendText ("No property \" " + propertyName + "\" " );
118
123
return notMatched ();
@@ -122,22 +127,19 @@ private Condition<PropertyDescriptor> propertyOn(T bean, Description mismatch) {
122
127
}
123
128
124
129
private Condition .Step <Method , Object > withPropertyValue (final T bean ) {
125
- return new Condition .Step <Method , Object >() {
126
- @ Override
127
- public Condition <Object > apply (Method readMethod , Description mismatch ) {
128
- try {
129
- return matched (readMethod .invoke (bean , NO_ARGUMENTS ), mismatch );
130
- } catch (InvocationTargetException e ) {
131
- mismatch
132
- .appendText ("Calling '" )
133
- .appendText (readMethod .toString ())
134
- .appendText ("': " )
135
- .appendValue (e .getTargetException ().getMessage ());
136
- return notMatched ();
137
- } catch (Exception e ) {
138
- throw new IllegalStateException (
139
- "Calling: '" + readMethod + "' should not have thrown " + e );
140
- }
130
+ return (readMethod , mismatch ) -> {
131
+ try {
132
+ return matched (readMethod .invoke (bean , NO_ARGUMENTS ), mismatch );
133
+ } catch (InvocationTargetException e ) {
134
+ mismatch
135
+ .appendText ("Calling '" )
136
+ .appendText (readMethod .toString ())
137
+ .appendText ("': " )
138
+ .appendValue (e .getTargetException ().getMessage ());
139
+ return notMatched ();
140
+ } catch (Exception e ) {
141
+ throw new IllegalStateException (
142
+ "Calling: '" + readMethod + "' should not have thrown " + e );
141
143
}
142
144
};
143
145
}
@@ -147,17 +149,16 @@ private static Matcher<Object> nastyGenericsWorkaround(Matcher<?> valueMatcher)
147
149
return (Matcher <Object >) valueMatcher ;
148
150
}
149
151
150
- private static Condition .Step <PropertyDescriptor , Method > withReadMethod () {
151
- return new Condition .Step <PropertyDescriptor , java .lang .reflect .Method >() {
152
- @ Override
153
- public Condition <Method > apply (PropertyDescriptor property , Description mismatch ) {
154
- final Method readMethod = property .getReadMethod ();
155
- if (null == readMethod ) {
156
- mismatch .appendText ("property \" " + property .getName () + "\" is not readable" );
157
- return notMatched ();
158
- }
159
- return matched (readMethod , mismatch );
152
+ private static Condition .Step <FeatureDescriptor , Method > withReadMethod () {
153
+ return (property , mismatch ) -> {
154
+ final Method readMethod = property instanceof PropertyDescriptor ?
155
+ ((PropertyDescriptor ) property ).getReadMethod () :
156
+ (((MethodDescriptor ) property ).getMethod ());
157
+ if (null == readMethod || readMethod .getReturnType () == void .class ) {
158
+ mismatch .appendText ("property \" " + property .getName () + "\" is not readable" );
159
+ return notMatched ();
160
160
}
161
+ return matched (readMethod , mismatch );
161
162
};
162
163
}
163
164
0 commit comments