1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.beans;
18
19 import org.junit.Rule;
20 import org.junit.Test;
21 import org.junit.rules.ExpectedException;
22
23 import static org.hamcrest.CoreMatchers.*;
24 import static org.junit.Assert.*;
25
26
27
28
29
30 public abstract class AbstractConfigurablePropertyAccessorTests {
31
32 @Rule
33 public final ExpectedException thrown = ExpectedException.none();
34
35
36 protected abstract ConfigurablePropertyAccessor createAccessor(Object target);
37
38 @Test
39 public void isReadableProperty() {
40 ConfigurablePropertyAccessor accessor = createAccessor(new Simple("John", 2));
41
42 assertThat(accessor.isReadableProperty("name"), is(true));
43 }
44
45 @Test
46 public void isReadablePropertyNotReadable() {
47 ConfigurablePropertyAccessor accessor = createAccessor(new NoRead());
48
49 assertFalse(accessor.isReadableProperty("age"));
50 }
51
52
53
54
55 @Test
56 public void isReadablePropertyNoSuchProperty() {
57 ConfigurablePropertyAccessor accessor = createAccessor(new NoRead());
58
59 assertFalse(accessor.isReadableProperty("xxxxx"));
60 }
61
62 @Test
63 public void isReadablePropertyNull() {
64 ConfigurablePropertyAccessor accessor = createAccessor(new NoRead());
65
66 thrown.expect(IllegalArgumentException.class);
67 accessor.isReadableProperty(null);
68 }
69
70 @Test
71 public void isWritableProperty() {
72 ConfigurablePropertyAccessor accessor = createAccessor(new Simple("John", 2));
73
74 assertThat(accessor.isWritableProperty("name"), is(true));
75 }
76
77 @Test
78 public void isWritablePropertyNull() {
79 ConfigurablePropertyAccessor accessor = createAccessor(new NoRead());
80
81 thrown.expect(IllegalArgumentException.class);
82 accessor.isWritableProperty(null);
83 }
84
85 @Test
86 public void isWritablePropertyNoSuchProperty() {
87 ConfigurablePropertyAccessor accessor = createAccessor(new NoRead());
88
89 assertFalse(accessor.isWritableProperty("xxxxx"));
90 }
91
92 @Test
93 public void getSimpleProperty() {
94 Simple simple = new Simple("John", 2);
95 ConfigurablePropertyAccessor accessor = createAccessor(simple);
96 assertThat(accessor.getPropertyValue("name"), is("John"));
97 }
98
99 @Test
100 public void getNestedProperty() {
101 Person person = createPerson("John", "London", "UK");
102 ConfigurablePropertyAccessor accessor = createAccessor(person);
103 assertThat(accessor.getPropertyValue("address.city"), is("London"));
104 }
105
106 @Test
107 public void getNestedDeepProperty() {
108 Person person = createPerson("John", "London", "UK");
109 ConfigurablePropertyAccessor accessor = createAccessor(person);
110
111 assertThat(accessor.getPropertyValue("address.country.name"), is("UK"));
112 }
113
114 @Test
115 public void getPropertyIntermediateFieldIsNull() {
116 Person person = createPerson("John", "London", "UK");
117 person.address = null;
118 ConfigurablePropertyAccessor accessor = createAccessor(person);
119
120 try {
121 accessor.getPropertyValue("address.country.name");
122 fail("Should have failed to get value with null intermediate path");
123 }
124 catch (NullValueInNestedPathException e) {
125 assertEquals("address", e.getPropertyName());
126 assertEquals(Person.class, e.getBeanClass());
127 }
128 }
129
130 @Test
131 public void getPropertyIntermediateFieldIsNullWithAutoGrow() {
132 Person person = createPerson("John", "London", "UK");
133 person.address = null;
134 ConfigurablePropertyAccessor accessor = createAccessor(person);
135 accessor.setAutoGrowNestedPaths(true);
136
137 assertEquals("DefaultCountry", accessor.getPropertyValue("address.country.name"));
138 }
139
140 @Test
141 public void getUnknownField() {
142 Simple simple = new Simple("John", 2);
143 ConfigurablePropertyAccessor accessor = createAccessor(simple);
144
145 try {
146 accessor.getPropertyValue("foo");
147 fail("Should have failed to get an unknown field.");
148 }
149 catch (NotReadablePropertyException e) {
150 assertEquals(Simple.class, e.getBeanClass());
151 assertEquals("foo", e.getPropertyName());
152 }
153 }
154
155 @Test
156 public void getUnknownNestedField() {
157 Person person = createPerson("John", "London", "UK");
158 ConfigurablePropertyAccessor accessor = createAccessor(person);
159
160 thrown.expect(NotReadablePropertyException.class);
161 accessor.getPropertyValue("address.bar");
162 }
163
164 @Test
165 public void setSimpleProperty() {
166 Simple simple = new Simple("John", 2);
167 ConfigurablePropertyAccessor accessor = createAccessor(simple);
168
169 accessor.setPropertyValue("name", "SomeValue");
170
171 assertThat(simple.name, is("SomeValue"));
172 assertThat(simple.getName(), is("SomeValue"));
173 }
174
175 @Test
176 public void setNestedProperty() {
177 Person person = createPerson("John", "Paris", "FR");
178 ConfigurablePropertyAccessor accessor = createAccessor(person);
179
180 accessor.setPropertyValue("address.city", "London");
181 assertThat(person.address.city, is("London"));
182 }
183
184 @Test
185 public void setNestedDeepProperty() {
186 Person person = createPerson("John", "Paris", "FR");
187 ConfigurablePropertyAccessor accessor = createAccessor(person);
188
189 accessor.setPropertyValue("address.country.name", "UK");
190 assertThat(person.address.country.name, is("UK"));
191 }
192
193 @Test
194 public void setPropertyIntermediateFieldIsNull() {
195 Person person = createPerson("John", "Paris", "FR");
196 person.address.country = null;
197 ConfigurablePropertyAccessor accessor = createAccessor(person);
198
199 try {
200 accessor.setPropertyValue("address.country.name", "UK");
201 fail("Should have failed to set value with intermediate null value");
202 }
203 catch (NullValueInNestedPathException e) {
204 assertEquals("address.country", e.getPropertyName());
205 assertEquals(Person.class, e.getBeanClass());
206 }
207 assertThat(person.address.country, is(nullValue()));
208 }
209
210 @Test
211 public void setPropertyIntermediateFieldIsNullWithAutoGrow() {
212 Person person = createPerson("John", "Paris", "FR");
213 person.address.country = null;
214 ConfigurablePropertyAccessor accessor = createAccessor(person);
215 accessor.setAutoGrowNestedPaths(true);
216
217 accessor.setPropertyValue("address.country.name", "UK");
218 assertThat(person.address.country.name, is("UK"));
219 }
220
221 @Test
222 public void setUnknownField() {
223 Simple simple = new Simple("John", 2);
224 ConfigurablePropertyAccessor accessor = createAccessor(simple);
225
226 try {
227 accessor.setPropertyValue("foo", "value");
228 fail("Should have failed to set an unknown field.");
229 }
230 catch (NotWritablePropertyException e) {
231 assertEquals(Simple.class, e.getBeanClass());
232 assertEquals("foo", e.getPropertyName());
233 }
234 }
235
236 @Test
237 public void setUnknownNestedField() {
238 Person person = createPerson("John", "Paris", "FR");
239 ConfigurablePropertyAccessor accessor = createAccessor(person);
240
241 thrown.expect(NotWritablePropertyException.class);
242 accessor.setPropertyValue("address.bar", "value");
243 }
244
245
246 @Test
247 public void propertyType() {
248 Person person = createPerson("John", "Paris", "FR");
249 ConfigurablePropertyAccessor accessor = createAccessor(person);
250
251 assertEquals(String.class, accessor.getPropertyType("address.city"));
252 }
253
254 @Test
255 public void propertyTypeUnknownField() {
256 Simple simple = new Simple("John", 2);
257 ConfigurablePropertyAccessor accessor = createAccessor(simple);
258
259 assertThat(accessor.getPropertyType("foo"), is(nullValue()));
260 }
261
262 @Test
263 public void propertyTypeDescriptor() {
264 Person person = createPerson("John", "Paris", "FR");
265 ConfigurablePropertyAccessor accessor = createAccessor(person);
266
267 assertThat(accessor.getPropertyTypeDescriptor("address.city"), is(notNullValue()));
268 }
269
270 @Test
271 public void propertyTypeDescriptorUnknownField() {
272 Simple simple = new Simple("John", 2);
273 ConfigurablePropertyAccessor accessor = createAccessor(simple);
274
275 assertThat(accessor.getPropertyTypeDescriptor("foo"), is(nullValue()));
276 }
277
278
279 private Person createPerson(String name, String city, String country) {
280 return new Person(name, new Address(city, country));
281 }
282
283
284 private static class Simple {
285
286 private String name;
287
288 private Integer integer;
289
290 private Simple(String name, Integer integer) {
291 this.name = name;
292 this.integer = integer;
293 }
294
295 public String getName() {
296 return name;
297 }
298
299 public void setName(String name) {
300 this.name = name;
301 }
302
303 public Integer getInteger() {
304 return integer;
305 }
306
307 public void setInteger(Integer integer) {
308 this.integer = integer;
309 }
310 }
311
312 private static class Person {
313 private String name;
314
315 private Address address;
316
317 private Person(String name, Address address) {
318 this.name = name;
319 this.address = address;
320 }
321
322 public Person() {
323 }
324
325 public String getName() {
326 return name;
327 }
328
329 public void setName(String name) {
330 this.name = name;
331 }
332
333 public Address getAddress() {
334 return address;
335 }
336
337 public void setAddress(Address address) {
338 this.address = address;
339 }
340 }
341
342 private static class Address {
343 private String city;
344
345 private Country country;
346
347 private Address(String city, String country) {
348 this.city = city;
349 this.country = new Country(country);
350 }
351
352 public Address() {
353 this("DefaultCity", "DefaultCountry");
354 }
355
356 public String getCity() {
357 return city;
358 }
359
360 public void setCity(String city) {
361 this.city = city;
362 }
363
364 public Country getCountry() {
365 return country;
366 }
367
368 public void setCountry(Country country) {
369 this.country = country;
370 }
371 }
372
373 private static class Country {
374 private String name;
375
376 public Country(String name) {
377 this.name = name;
378 }
379
380 public Country() {
381 this(null);
382 }
383
384 public String getName() {
385 return name;
386 }
387
388 public void setName(String name) {
389 this.name = name;
390 }
391 }
392
393
394 @SuppressWarnings("unused")
395 static class NoRead {
396
397 public void setAge(int age) {
398 }
399 }
400 }