1 package org.hamcrest.beans;
2 
3 import org.hamcrest.AbstractMatcherTest;
4 import org.hamcrest.Description;
5 import org.hamcrest.Matcher;
6 import org.hamcrest.StringDescription;
7 import org.hamcrest.core.IsEqual;
8 
9 import java.beans.IntrospectionException;
10 import java.beans.PropertyDescriptor;
11 import java.beans.SimpleBeanInfo;
12 
13 import static org.hamcrest.MatcherAssert.assertThat;
14 import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
15 import static org.hamcrest.core.IsAnything.anything;
16 import static org.hamcrest.core.IsEqual.equalTo;
17 
18 /**
19  * @author Iain McGinniss
20  * @author Nat Pryce
21  * @author Steve Freeman
22  * @since 1.1.0
23  */
24 @SuppressWarnings("UnusedDeclaration")
25 public class HasPropertyWithValueTest extends AbstractMatcherTest {
26   private final BeanWithoutInfo shouldMatch = new BeanWithoutInfo("is expected");
27   private final BeanWithoutInfo shouldNotMatch = new BeanWithoutInfo("not expected");
28 
29   private final BeanWithInfo beanWithInfo = new BeanWithInfo("with info");
30 
31   @Override
createMatcher()32   protected Matcher<?> createMatcher() {
33     return hasProperty("irrelevant", anything());
34   }
35 
testMatchesInfolessBeanWithMatchedNamedProperty()36   public void testMatchesInfolessBeanWithMatchedNamedProperty() {
37     assertMatches("with property", hasProperty("property", equalTo("is expected")), shouldMatch);
38     assertMismatchDescription("property 'property' was \"not expected\"",
39                               hasProperty("property", equalTo("is expected")), shouldNotMatch);
40   }
41 
testMatchesBeanWithInfoWithMatchedNamedProperty()42   public void testMatchesBeanWithInfoWithMatchedNamedProperty() {
43     assertMatches("with bean info", hasProperty("property", equalTo("with info")), beanWithInfo);
44     assertMismatchDescription("property 'property' was \"with info\"",
45         hasProperty("property", equalTo("without info")), beanWithInfo);
46   }
47 
testDoesNotMatchInfolessBeanWithoutMatchedNamedProperty()48   public void testDoesNotMatchInfolessBeanWithoutMatchedNamedProperty() {
49     assertMismatchDescription("No property \"nonExistentProperty\"",
50                               hasProperty("nonExistentProperty", anything()), shouldNotMatch);
51    }
52 
testDoesNotMatchWriteOnlyProperty()53   public void testDoesNotMatchWriteOnlyProperty() {
54     assertMismatchDescription("property \"writeOnlyProperty\" is not readable",
55                               hasProperty("writeOnlyProperty", anything()), shouldNotMatch);
56   }
57 
testDescribeTo()58   public void testDescribeTo() {
59     assertDescription("hasProperty(\"property\", <true>)", hasProperty("property", equalTo(true)));
60   }
61 
testMatchesPropertyAndValue()62   public void testMatchesPropertyAndValue() {
63     assertMatches("property with value", hasProperty( "property", anything()), beanWithInfo);
64   }
65 
testDoesNotWriteMismatchIfPropertyMatches()66   public void testDoesNotWriteMismatchIfPropertyMatches() {
67     Description description = new StringDescription();
68     hasProperty( "property", anything()).describeMismatch(beanWithInfo, description);
69     assertEquals("Expected mismatch description", "", description.toString());
70   }
71 
testDescribesMissingPropertyMismatch()72   public void testDescribesMissingPropertyMismatch() {
73     assertMismatchDescription("No property \"honk\"", hasProperty( "honk", anything()), shouldNotMatch);
74   }
75 
testCanAccessAnAnonymousInnerClass()76   public void testCanAccessAnAnonymousInnerClass() {
77     class X implements IX {
78       @Override
79       public int getTest() {
80         return 1;
81       }
82     }
83 
84     assertThat(new X(), HasPropertyWithValue.hasProperty("test", IsEqual.equalTo(1)));
85   }
86 
87   interface IX {
getTest()88     int getTest();
89   }
90 
91   public static class BeanWithoutInfo {
92     private String property;
93 
BeanWithoutInfo(String property)94     public BeanWithoutInfo(String property) {
95       this.property = property;
96     }
97 
getProperty()98     public String getProperty() {
99       return property;
100     }
101 
setProperty(String property)102     public void setProperty(String property) {
103       this.property = property;
104     }
105 
setWriteOnlyProperty(@uppressWarnings"unused") float property)106     public void setWriteOnlyProperty(@SuppressWarnings("unused") float property) {
107     }
108 
109     @Override
toString()110     public String toString() {
111       return "[Person: " + property + "]";
112     }
113   }
114 
115   public static class BeanWithInfo {
116     private final String propertyValue;
117 
BeanWithInfo(String propertyValue)118     public BeanWithInfo(String propertyValue) {
119       this.propertyValue = propertyValue;
120     }
121 
property()122     public String property() {
123       return propertyValue;
124     }
125   }
126 
127   public static class BeanWithInfoBeanInfo extends SimpleBeanInfo {
128     @Override
getPropertyDescriptors()129     public PropertyDescriptor[] getPropertyDescriptors() {
130       try {
131         return new PropertyDescriptor[] {
132             new PropertyDescriptor("property", BeanWithInfo.class, "property", null)
133           };
134       } catch (IntrospectionException e) {
135         throw new RuntimeException("Introspection exception: " + e.getMessage());
136       }
137     }
138   }
139 }
140