1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.core.env;
18
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Properties;
22
23 import org.junit.Before;
24 import org.junit.Test;
25
26 import org.springframework.core.convert.ConversionException;
27 import org.springframework.mock.env.MockPropertySource;
28
29 import static org.hamcrest.Matchers.*;
30 import static org.junit.Assert.*;
31
32
33
34
35
36 public class PropertySourcesPropertyResolverTests {
37
38 private Properties testProperties;
39
40 private MutablePropertySources propertySources;
41
42 private ConfigurablePropertyResolver propertyResolver;
43
44
45 @Before
46 public void setUp() {
47 propertySources = new MutablePropertySources();
48 propertyResolver = new PropertySourcesPropertyResolver(propertySources);
49 testProperties = new Properties();
50 propertySources.addFirst(new PropertiesPropertySource("testProperties", testProperties));
51 }
52
53
54 @Test
55 public void containsProperty() {
56 assertThat(propertyResolver.containsProperty("foo"), is(false));
57 testProperties.put("foo", "bar");
58 assertThat(propertyResolver.containsProperty("foo"), is(true));
59 }
60
61 @Test
62 public void getProperty() {
63 assertThat(propertyResolver.getProperty("foo"), nullValue());
64 testProperties.put("foo", "bar");
65 assertThat(propertyResolver.getProperty("foo"), is("bar"));
66 }
67
68 @Test
69 public void getProperty_withDefaultValue() {
70 assertThat(propertyResolver.getProperty("foo", "myDefault"), is("myDefault"));
71 testProperties.put("foo", "bar");
72 assertThat(propertyResolver.getProperty("foo"), is("bar"));
73 }
74
75 @Test
76 public void getProperty_propertySourceSearchOrderIsFIFO() {
77 MutablePropertySources sources = new MutablePropertySources();
78 PropertyResolver resolver = new PropertySourcesPropertyResolver(sources);
79 sources.addFirst(new MockPropertySource("ps1").withProperty("pName", "ps1Value"));
80 assertThat(resolver.getProperty("pName"), equalTo("ps1Value"));
81 sources.addFirst(new MockPropertySource("ps2").withProperty("pName", "ps2Value"));
82 assertThat(resolver.getProperty("pName"), equalTo("ps2Value"));
83 sources.addFirst(new MockPropertySource("ps3").withProperty("pName", "ps3Value"));
84 assertThat(resolver.getProperty("pName"), equalTo("ps3Value"));
85 }
86
87 @Test
88 public void getProperty_withExplicitNullValue() {
89
90 Map<String, Object> nullableProperties = new HashMap<String, Object>();
91 propertySources.addLast(new MapPropertySource("nullableProperties", nullableProperties));
92 nullableProperties.put("foo", null);
93 assertThat(propertyResolver.getProperty("foo"), nullValue());
94 }
95
96 @Test
97 public void getProperty_withTargetType_andDefaultValue() {
98 assertThat(propertyResolver.getProperty("foo", Integer.class, 42), equalTo(42));
99 testProperties.put("foo", 13);
100 assertThat(propertyResolver.getProperty("foo", Integer.class, 42), equalTo(13));
101 }
102
103 @Test
104 public void getProperty_withStringArrayConversion() {
105 testProperties.put("foo", "bar,baz");
106 assertThat(propertyResolver.getProperty("foo", String[].class), equalTo(new String[] { "bar", "baz" }));
107 }
108
109 @Test
110 public void getProperty_withNonConvertibleTargetType() {
111 testProperties.put("foo", "bar");
112
113 class TestType { }
114
115 try {
116 propertyResolver.getProperty("foo", TestType.class);
117 fail("Expected IllegalArgumentException due to non-convertible types");
118 }
119 catch (IllegalArgumentException ex) {
120
121 }
122 }
123
124 @Test
125 public void getProperty_doesNotCache_replaceExistingKeyPostConstruction() {
126 String key = "foo";
127 String value1 = "bar";
128 String value2 = "biz";
129
130 HashMap<String, Object> map = new HashMap<String, Object>();
131 map.put(key, value1);
132 MutablePropertySources propertySources = new MutablePropertySources();
133 propertySources.addFirst(new MapPropertySource("testProperties", map));
134 PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
135 assertThat(propertyResolver.getProperty(key), equalTo(value1));
136 map.put(key, value2);
137 assertThat(propertyResolver.getProperty(key), equalTo(value2));
138 }
139
140 @Test
141 public void getProperty_doesNotCache_addNewKeyPostConstruction() {
142 HashMap<String, Object> map = new HashMap<String, Object>();
143 MutablePropertySources propertySources = new MutablePropertySources();
144 propertySources.addFirst(new MapPropertySource("testProperties", map));
145 PropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
146 assertThat(propertyResolver.getProperty("foo"), equalTo(null));
147 map.put("foo", "42");
148 assertThat(propertyResolver.getProperty("foo"), equalTo("42"));
149 }
150
151 @Test
152 public void getPropertySources_replacePropertySource() {
153 propertySources = new MutablePropertySources();
154 propertyResolver = new PropertySourcesPropertyResolver(propertySources);
155 propertySources.addLast(new MockPropertySource("local").withProperty("foo", "localValue"));
156 propertySources.addLast(new MockPropertySource("system").withProperty("foo", "systemValue"));
157
158
159 assertThat(propertyResolver.getProperty("foo"), equalTo("localValue"));
160
161
162 propertySources.replace("local", new MockPropertySource("new").withProperty("foo", "newValue"));
163
164
165 assertThat(propertyResolver.getProperty("foo"), equalTo("newValue"));
166
167 assertThat(propertySources.size(), is(2));
168 }
169
170 @Test
171 public void getRequiredProperty() {
172 testProperties.put("exists", "xyz");
173 assertThat(propertyResolver.getRequiredProperty("exists"), is("xyz"));
174
175 try {
176 propertyResolver.getRequiredProperty("bogus");
177 fail("expected IllegalStateException");
178 }
179 catch (IllegalStateException ex) {
180
181 }
182 }
183
184 @Test
185 public void getRequiredProperty_withStringArrayConversion() {
186 testProperties.put("exists", "abc,123");
187 assertThat(propertyResolver.getRequiredProperty("exists", String[].class), equalTo(new String[] { "abc", "123" }));
188
189 try {
190 propertyResolver.getRequiredProperty("bogus", String[].class);
191 fail("expected IllegalStateException");
192 }
193 catch (IllegalStateException ex) {
194
195 }
196 }
197
198 @Test
199 public void resolvePlaceholders() {
200 MutablePropertySources propertySources = new MutablePropertySources();
201 propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
202 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
203 assertThat(resolver.resolvePlaceholders("Replace this ${key}"), equalTo("Replace this value"));
204 }
205
206 @Test
207 public void resolvePlaceholders_withUnresolvable() {
208 MutablePropertySources propertySources = new MutablePropertySources();
209 propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
210 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
211 assertThat(resolver.resolvePlaceholders("Replace this ${key} plus ${unknown}"),
212 equalTo("Replace this value plus ${unknown}"));
213 }
214
215 @Test
216 public void resolvePlaceholders_withDefaultValue() {
217 MutablePropertySources propertySources = new MutablePropertySources();
218 propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
219 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
220 assertThat(resolver.resolvePlaceholders("Replace this ${key} plus ${unknown:defaultValue}"),
221 equalTo("Replace this value plus defaultValue"));
222 }
223
224 @Test(expected=IllegalArgumentException.class)
225 public void resolvePlaceholders_withNullInput() {
226 new PropertySourcesPropertyResolver(new MutablePropertySources()).resolvePlaceholders(null);
227 }
228
229 @Test
230 public void resolveRequiredPlaceholders() {
231 MutablePropertySources propertySources = new MutablePropertySources();
232 propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
233 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
234 assertThat(resolver.resolveRequiredPlaceholders("Replace this ${key}"), equalTo("Replace this value"));
235 }
236
237 @Test(expected=IllegalArgumentException.class)
238 public void resolveRequiredPlaceholders_withUnresolvable() {
239 MutablePropertySources propertySources = new MutablePropertySources();
240 propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
241 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
242 resolver.resolveRequiredPlaceholders("Replace this ${key} plus ${unknown}");
243 }
244
245 @Test
246 public void resolveRequiredPlaceholders_withDefaultValue() {
247 MutablePropertySources propertySources = new MutablePropertySources();
248 propertySources.addFirst(new MockPropertySource().withProperty("key", "value"));
249 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
250 assertThat(resolver.resolveRequiredPlaceholders("Replace this ${key} plus ${unknown:defaultValue}"),
251 equalTo("Replace this value plus defaultValue"));
252 }
253
254 @Test(expected=IllegalArgumentException.class)
255 public void resolveRequiredPlaceholders_withNullInput() {
256 new PropertySourcesPropertyResolver(new MutablePropertySources()).resolveRequiredPlaceholders(null);
257 }
258
259 @Test
260 public void getPropertyAsClass() throws ClassNotFoundException, LinkageError {
261 MutablePropertySources propertySources = new MutablePropertySources();
262 propertySources.addFirst(new MockPropertySource().withProperty("some.class", SpecificType.class.getName()));
263 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
264 assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
265 }
266
267 @Test
268 public void getPropertyAsClass_withInterfaceAsTarget() throws ClassNotFoundException, LinkageError {
269 MutablePropertySources propertySources = new MutablePropertySources();
270 propertySources.addFirst(new MockPropertySource().withProperty("some.class", SomeType.class.getName()));
271 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
272 assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SomeType.class));
273 }
274
275 @Test(expected=ConversionException.class)
276 public void getPropertyAsClass_withMismatchedTypeForValue() {
277 MutablePropertySources propertySources = new MutablePropertySources();
278 propertySources.addFirst(new MockPropertySource().withProperty("some.class", "java.lang.String"));
279 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
280 resolver.getPropertyAsClass("some.class", SomeType.class);
281 }
282
283 @Test(expected=ConversionException.class)
284 public void getPropertyAsClass_withNonExistentClassForValue() {
285 MutablePropertySources propertySources = new MutablePropertySources();
286 propertySources.addFirst(new MockPropertySource().withProperty("some.class", "some.bogus.Class"));
287 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
288 resolver.getPropertyAsClass("some.class", SomeType.class);
289 }
290
291 @Test
292 public void getPropertyAsClass_withObjectForValue() {
293 MutablePropertySources propertySources = new MutablePropertySources();
294 propertySources.addFirst(new MockPropertySource().withProperty("some.class", new SpecificType()));
295 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
296 assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
297 }
298
299 @Test(expected=ConversionException.class)
300 public void getPropertyAsClass_withMismatchedObjectForValue() {
301 MutablePropertySources propertySources = new MutablePropertySources();
302 propertySources.addFirst(new MockPropertySource().withProperty("some.class", new Integer(42)));
303 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
304 resolver.getPropertyAsClass("some.class", SomeType.class);
305 }
306
307 @Test
308 public void getPropertyAsClass_withRealClassForValue() {
309 MutablePropertySources propertySources = new MutablePropertySources();
310 propertySources.addFirst(new MockPropertySource().withProperty("some.class", SpecificType.class));
311 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
312 assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
313 }
314
315 @Test(expected=ConversionException.class)
316 public void getPropertyAsClass_withMismatchedRealClassForValue() {
317 MutablePropertySources propertySources = new MutablePropertySources();
318 propertySources.addFirst(new MockPropertySource().withProperty("some.class", Integer.class));
319 PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
320 resolver.getPropertyAsClass("some.class", SomeType.class);
321 }
322
323 @Test
324 public void setRequiredProperties_andValidateRequiredProperties() {
325
326 propertyResolver.validateRequiredProperties();
327
328
329 propertyResolver.setRequiredProperties("foo", "bar");
330
331
332 try {
333 propertyResolver.validateRequiredProperties();
334 fail("expected validation exception");
335 }
336 catch (MissingRequiredPropertiesException ex) {
337 assertThat(ex.getMessage(), equalTo(
338 "The following properties were declared as required " +
339 "but could not be resolved: [foo, bar]"));
340 }
341
342
343 testProperties.put("foo", "fooValue");
344 try {
345 propertyResolver.validateRequiredProperties();
346 fail("expected validation exception");
347 }
348 catch (MissingRequiredPropertiesException ex) {
349 assertThat(ex.getMessage(), equalTo(
350 "The following properties were declared as required " +
351 "but could not be resolved: [bar]"));
352 }
353
354
355 testProperties.put("bar", "");
356 propertyResolver.validateRequiredProperties();
357 }
358
359 @Test
360 public void resolveNestedPropertyPlaceholders() {
361 MutablePropertySources ps = new MutablePropertySources();
362 ps.addFirst(new MockPropertySource()
363 .withProperty("p1", "v1")
364 .withProperty("p2", "v2")
365 .withProperty("p3", "${p1}:${p2}")
366 .withProperty("p4", "${p3}")
367 .withProperty("p5", "${p1}:${p2}:${bogus}")
368 .withProperty("p6", "${p1}:${p2}:${bogus:def}")
369 .withProperty("pL", "${pR}")
370 .withProperty("pR", "${pL}")
371 );
372 ConfigurablePropertyResolver pr = new PropertySourcesPropertyResolver(ps);
373 assertThat(pr.getProperty("p1"), equalTo("v1"));
374 assertThat(pr.getProperty("p2"), equalTo("v2"));
375 assertThat(pr.getProperty("p3"), equalTo("v1:v2"));
376 assertThat(pr.getProperty("p4"), equalTo("v1:v2"));
377 try {
378 pr.getProperty("p5");
379 }
380 catch (IllegalArgumentException ex) {
381 assertThat(ex.getMessage(), containsString(
382 "Could not resolve placeholder 'bogus' in string value \"${p1}:${p2}:${bogus}\""));
383 }
384 assertThat(pr.getProperty("p6"), equalTo("v1:v2:def"));
385 try {
386 pr.getProperty("pL");
387 }
388 catch (IllegalArgumentException ex) {
389 assertTrue(ex.getMessage().toLowerCase().contains("circular"));
390 }
391 }
392
393 @Test
394 public void ignoreUnresolvableNestedPlaceholdersIsConfigurable() {
395 MutablePropertySources ps = new MutablePropertySources();
396 ps.addFirst(new MockPropertySource()
397 .withProperty("p1", "v1")
398 .withProperty("p2", "v2")
399 .withProperty("p3", "${p1}:${p2}:${bogus:def}")
400 .withProperty("p4", "${p1}:${p2}:${bogus}")
401 );
402 ConfigurablePropertyResolver pr = new PropertySourcesPropertyResolver(ps);
403 assertThat(pr.getProperty("p1"), equalTo("v1"));
404 assertThat(pr.getProperty("p2"), equalTo("v2"));
405 assertThat(pr.getProperty("p3"), equalTo("v1:v2:def"));
406
407
408
409 try {
410 pr.getProperty("p4");
411 }
412 catch (IllegalArgumentException ex) {
413 assertThat(ex.getMessage(), containsString(
414 "Could not resolve placeholder 'bogus' in string value \"${p1}:${p2}:${bogus}\""));
415 }
416
417
418 pr.setIgnoreUnresolvableNestedPlaceholders(true);
419
420 assertThat(pr.getProperty("p4"), equalTo("v1:v2:${bogus}"));
421
422
423
424 assertThat(pr.resolvePlaceholders("${p1}:${p2}:${bogus}"), equalTo("v1:v2:${bogus}"));
425 try {
426 pr.resolveRequiredPlaceholders("${p1}:${p2}:${bogus}");
427 }
428 catch (IllegalArgumentException ex) {
429 assertThat(ex.getMessage(), containsString(
430 "Could not resolve placeholder 'bogus' in string value \"${p1}:${p2}:${bogus}\""));
431 }
432 }
433
434
435 interface SomeType {
436 }
437
438 static class SpecificType implements SomeType {
439 }
440
441 }