summaryrefslogtreecommitdiff
path: root/spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java
blob: ec2528af29a75cac532711778d64a8803db2454b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.test.context;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;

/**
 * {@code @TestPropertySource} is a class-level annotation that is used to
 * configure the {@link #locations} of properties files and inlined
 * {@link #properties} to be added to the {@code Environment}'s set of
 * {@code PropertySources} for an
 * {@link org.springframework.context.ApplicationContext ApplicationContext}
 * for integration tests.
 *
 * <h3>Precedence</h3>
 * <p>Test property sources have higher precedence than those loaded from the
 * operating system's environment or Java system properties as well as property
 * sources added by the application declaratively via
 * {@link org.springframework.context.annotation.PropertySource @PropertySource}
 * or programmatically (e.g., via an
 * {@link org.springframework.context.ApplicationContextInitializer ApplicationContextInitializer}
 * or some other means). Thus, test property sources can be used to selectively
 * override properties defined in system and application property sources.
 * Furthermore, inlined {@link #properties} have higher precedence than
 * properties loaded from resource {@link #locations}.
 *
 * <h3>Default Properties File Detection</h3>
 * <p>If {@code @TestPropertySource} is declared as an <em>empty</em> annotation
 * (i.e., without explicit values for {@link #locations} or {@link #properties}),
 * an attempt will be made to detect a <em>default</em> properties file relative
 * to the class that declared the annotation. For example, if the annotated test
 * class is {@code com.example.MyTest}, the corresponding default properties file
 * is {@code "classpath:com/example/MyTest.properties"}. If the default cannot be
 * detected, an {@link IllegalStateException} will be thrown.
 *
 * <h3>Enabling &#064;TestPropertySource</h3>
 * <p>{@code @TestPropertySource} is enabled if the configured
 * {@linkplain ContextConfiguration#loader context loader} honors it. Every
 * {@code SmartContextLoader} that is a subclass of either
 * {@link org.springframework.test.context.support.AbstractGenericContextLoader AbstractGenericContextLoader} or
 * {@link org.springframework.test.context.web.AbstractGenericWebContextLoader AbstractGenericWebContextLoader}
 * provides automatic support for {@code @TestPropertySource}, and this includes
 * every {@code SmartContextLoader} provided by the Spring TestContext Framework.
 *
 * <h3>Miscellaneous</h3>
 * <ul>
 * <li>Typically, {@code @TestPropertySource} will be used in conjunction with
 * {@link ContextConfiguration @ContextConfiguration}.</li>
 * <li>This annotation may be used as a <em>meta-annotation</em> to create
 * custom <em>composed annotations</em>; however, caution should be taken if
 * this annotation and {@code @ContextConfiguration} are combined on a composed
 * annotation since the {@code locations} and {@code inheritLocations} attributes
 * of both annotations can lead to ambiguity during the attribute resolution
 * process.</li>
 * </ul>
 *
 * @author Sam Brannen
 * @since 4.1
 * @see ContextConfiguration
 * @see org.springframework.core.env.Environment
 * @see org.springframework.core.env.PropertySource
 * @see org.springframework.context.annotation.PropertySource
 */
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestPropertySource {

	/**
	 * Alias for {@link #locations}.
	 * <p>This attribute may <strong>not</strong> be used in conjunction with
	 * {@link #locations}, but it may be used <em>instead</em> of {@link #locations}.
	 * @see #locations
	 */
	@AliasFor("locations")
	String[] value() default {};

	/**
	 * The resource locations of properties files to be loaded into the
	 * {@code Environment}'s set of {@code PropertySources}. Each location
	 * will be added to the enclosing {@code Environment} as its own property
	 * source, in the order declared.
	 * <h3>Supported File Formats</h3>
	 * <p>Both traditional and XML-based properties file formats are supported
	 * &mdash; for example, {@code "classpath:/com/example/test.properties"}
	 * or {@code "file:/path/to/file.xml"}.
	 * <h3>Path Resource Semantics</h3>
	 * <p>Each path will be interpreted as a Spring
	 * {@link org.springframework.core.io.Resource Resource}. A plain path
	 * &mdash; for example, {@code "test.properties"} &mdash; will be treated as a
	 * classpath resource that is <em>relative</em> to the package in which the
	 * test class is defined. A path starting with a slash will be treated as an
	 * <em>absolute</em> classpath resource, for example:
	 * {@code "/org/example/test.xml"}. A path which references a
	 * URL (e.g., a path prefixed with
	 * {@link org.springframework.util.ResourceUtils#CLASSPATH_URL_PREFIX classpath:},
	 * {@link org.springframework.util.ResourceUtils#FILE_URL_PREFIX file:},
	 * {@code http:}, etc.) will be loaded using the specified resource protocol.
	 * Resource location wildcards (e.g. <code>*&#42;/*.properties</code>)
	 * are not permitted: each location must evaluate to exactly one
	 * {@code .properties} or {@code .xml} resource. Property placeholders
	 * in paths (i.e., <code>${...}</code>) will be
	 * {@linkplain org.springframework.core.env.Environment#resolveRequiredPlaceholders(String) resolved}
	 * against the {@code Environment}.
	 * <h3>Default Properties File Detection</h3>
	 * <p>See the class-level Javadoc for a discussion on detection of defaults.
	 * <h3>Precedence</h3>
	 * <p>Properties loaded from resource locations have lower precedence than
	 * inlined {@link #properties}.
	 * <p>This attribute may <strong>not</strong> be used in conjunction with
	 * {@link #value}, but it may be used <em>instead</em> of {@link #value}.
	 * @see #inheritLocations
	 * @see #value
	 * @see #properties
	 * @see org.springframework.core.env.PropertySource
	 */
	@AliasFor("value")
	String[] locations() default {};

	/**
	 * Whether or not test property source {@link #locations} from superclasses
	 * should be <em>inherited</em>.
	 * <p>The default value is {@code true}, which means that a test class will
	 * <em>inherit</em> property source locations defined by a superclass.
	 * Specifically, the property source locations for a test class will be
	 * appended to the list of property source locations defined by a superclass.
	 * Thus, subclasses have the option of <em>extending</em> the list of test
	 * property source locations.
	 * <p>If {@code inheritLocations} is set to {@code false}, the property
	 * source locations for the test class will <em>shadow</em> and effectively
	 * replace any property source locations defined by a superclass.
	 * <p>In the following example, the {@code ApplicationContext} for
	 * {@code BaseTest} will be loaded using only the {@code "base.properties"}
	 * file as a test property source. In contrast, the {@code ApplicationContext}
	 * for {@code ExtendedTest} will be loaded using the {@code "base.properties"}
	 * <strong>and</strong> {@code "extended.properties"} files as test property
	 * source locations.
	 * <pre class="code">
	 * &#064;TestPropertySource(&quot;base.properties&quot;)
	 * &#064;ContextConfiguration
	 * public class BaseTest {
	 *   // ...
	 * }
	 *
	 * &#064;TestPropertySource(&quot;extended.properties&quot;)
	 * &#064;ContextConfiguration
	 * public class ExtendedTest extends BaseTest {
	 *   // ...
	 * }
	 * </pre>
	 *
	 * @see #locations
	 */
	boolean inheritLocations() default true;

	/**
	 * <em>Inlined properties</em> in the form of <em>key-value</em> pairs that
	 * should be added to the Spring
	 * {@link org.springframework.core.env.Environment Environment} before the
	 * {@code ApplicationContext} is loaded for the test. All key-value pairs
	 * will be added to the enclosing {@code Environment} as a single test
	 * {@code PropertySource} with the highest precedence.
	 * <h3>Supported Syntax</h3>
	 * <p>The supported syntax for key-value pairs is the same as the
	 * syntax defined for entries in a Java
	 * {@linkplain java.util.Properties#load(java.io.Reader) properties file}:
	 * <ul>
	 * <li>{@code "key=value"}</li>
	 * <li>{@code "key:value"}</li>
	 * <li>{@code "key value"}</li>
	 * </ul>
	 * <h3>Precedence</h3>
	 * <p>Properties declared via this attribute have higher precedence than
	 * properties loaded from resource {@link #locations}.
	 * <p>This attribute may be used in conjunction with {@link #value}
	 * <em>or</em> {@link #locations}.
	 * @see #inheritProperties
	 * @see #locations
	 * @see org.springframework.core.env.PropertySource
	 */
	String[] properties() default {};

	/**
	 * Whether or not inlined test {@link #properties} from superclasses should
	 * be <em>inherited</em>.
	 * <p>The default value is {@code true}, which means that a test class will
	 * <em>inherit</em> inlined properties defined by a superclass. Specifically,
	 * the inlined properties for a test class will be appended to the list of
	 * inlined properties defined by a superclass. Thus, subclasses have the
	 * option of <em>extending</em> the list of inlined test properties.
	 * <p>If {@code inheritProperties} is set to {@code false}, the inlined
	 * properties for the test class will <em>shadow</em> and effectively
	 * replace any inlined properties defined by a superclass.
	 * <p>In the following example, the {@code ApplicationContext} for
	 * {@code BaseTest} will be loaded using only the inlined {@code key1}
	 * property. In contrast, the {@code ApplicationContext} for
	 * {@code ExtendedTest} will be loaded using the inlined {@code key1}
	 * <strong>and</strong> {@code key2} properties.
	 * <pre class="code">
	 * &#064;TestPropertySource(properties = &quot;key1 = value1&quot;)
	 * &#064;ContextConfiguration
	 * public class BaseTest {
	 *   // ...
	 * }
	 * &#064;TestPropertySource(properties = &quot;key2 = value2&quot;)
	 * &#064;ContextConfiguration
	 * public class ExtendedTest extends BaseTest {
	 *   // ...
	 * }
	 * </pre>
	 * @see #properties
	 */
	boolean inheritProperties() default true;

}