001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.test.context;
018
019import java.lang.annotation.Documented;
020import java.lang.annotation.ElementType;
021import java.lang.annotation.Inherited;
022import java.lang.annotation.Repeatable;
023import java.lang.annotation.Retention;
024import java.lang.annotation.RetentionPolicy;
025import java.lang.annotation.Target;
026
027import org.springframework.core.annotation.AliasFor;
028
029/**
030 * {@code @TestPropertySource} is a class-level annotation that is used to
031 * configure the {@link #locations} of properties files and inlined
032 * {@link #properties} to be added to the {@code Environment}'s set of
033 * {@code PropertySources} for an
034 * {@link org.springframework.context.ApplicationContext ApplicationContext}
035 * for integration tests.
036 *
037 * <h3>Precedence</h3>
038 * <p>Test property sources have higher precedence than those loaded from the
039 * operating system's environment or Java system properties as well as property
040 * sources added by the application declaratively via
041 * {@link org.springframework.context.annotation.PropertySource @PropertySource}
042 * or programmatically (e.g., via an
043 * {@link org.springframework.context.ApplicationContextInitializer ApplicationContextInitializer}
044 * or some other means). Thus, test property sources can be used to selectively
045 * override properties defined in system and application property sources.
046 * Furthermore, inlined {@link #properties} have higher precedence than
047 * properties loaded from resource {@link #locations}. Note, however, that
048 * properties registered via {@link DynamicPropertySource @DynamicPropertySource}
049 * have higher precedence than those loaded via {@code @TestPropertySource}.
050 *
051 * <h3>Default Properties File Detection</h3>
052 * <p>If {@code @TestPropertySource} is declared as an <em>empty</em> annotation
053 * (i.e., without explicit values for {@link #locations} or {@link #properties}),
054 * an attempt will be made to detect a <em>default</em> properties file relative
055 * to the class that declared the annotation. For example, if the annotated test
056 * class is {@code com.example.MyTest}, the corresponding default properties file
057 * is {@code "classpath:com/example/MyTest.properties"}. If the default cannot be
058 * detected, an {@link IllegalStateException} will be thrown.
059 *
060 * <h3>Enabling &#064;TestPropertySource</h3>
061 * <p>{@code @TestPropertySource} is enabled if the configured
062 * {@linkplain ContextConfiguration#loader context loader} honors it. Every
063 * {@code SmartContextLoader} that is a subclass of either
064 * {@link org.springframework.test.context.support.AbstractGenericContextLoader AbstractGenericContextLoader} or
065 * {@link org.springframework.test.context.web.AbstractGenericWebContextLoader AbstractGenericWebContextLoader}
066 * provides automatic support for {@code @TestPropertySource}, and this includes
067 * every {@code SmartContextLoader} provided by the Spring TestContext Framework.
068 *
069 * <h3>Miscellaneous</h3>
070 * <ul>
071 * <li>Typically, {@code @TestPropertySource} will be used in conjunction with
072 * {@link ContextConfiguration @ContextConfiguration}.</li>
073 * <li>As of Spring Framework 5.2, {@code @TestPropertySource} can be used as a
074 * <em>{@linkplain Repeatable repeatable}</em> annotation.</li>
075 * <li>This annotation may be used as a <em>meta-annotation</em> to create
076 * custom <em>composed annotations</em>; however, caution should be taken if
077 * this annotation and {@code @ContextConfiguration} are combined on a composed
078 * annotation since the {@code locations} and {@code inheritLocations} attributes
079 * of both annotations can lead to ambiguity during the attribute resolution
080 * process.</li>
081 * </ul>
082 *
083 * @author Sam Brannen
084 * @since 4.1
085 * @see ContextConfiguration
086 * @see DynamicPropertySource
087 * @see org.springframework.core.env.Environment
088 * @see org.springframework.core.env.PropertySource
089 * @see org.springframework.context.annotation.PropertySource
090 */
091@Target(ElementType.TYPE)
092@Retention(RetentionPolicy.RUNTIME)
093@Documented
094@Inherited
095@Repeatable(TestPropertySources.class)
096public @interface TestPropertySource {
097
098        /**
099         * Alias for {@link #locations}.
100         * <p>This attribute may <strong>not</strong> be used in conjunction with
101         * {@link #locations}, but it may be used <em>instead</em> of {@link #locations}.
102         * @see #locations
103         */
104        @AliasFor("locations")
105        String[] value() default {};
106
107        /**
108         * The resource locations of properties files to be loaded into the
109         * {@code Environment}'s set of {@code PropertySources}. Each location
110         * will be added to the enclosing {@code Environment} as its own property
111         * source, in the order declared.
112         * <h3>Supported File Formats</h3>
113         * <p>Both traditional and XML-based properties file formats are supported
114         * &mdash; for example, {@code "classpath:/com/example/test.properties"}
115         * or {@code "file:/path/to/file.xml"}.
116         * <h3>Path Resource Semantics</h3>
117         * <p>Each path will be interpreted as a Spring
118         * {@link org.springframework.core.io.Resource Resource}. A plain path
119         * &mdash; for example, {@code "test.properties"} &mdash; will be treated as a
120         * classpath resource that is <em>relative</em> to the package in which the
121         * test class is defined. A path starting with a slash will be treated as an
122         * <em>absolute</em> classpath resource, for example:
123         * {@code "/org/example/test.xml"}. A path which references a
124         * URL (e.g., a path prefixed with
125         * {@link org.springframework.util.ResourceUtils#CLASSPATH_URL_PREFIX classpath:},
126         * {@link org.springframework.util.ResourceUtils#FILE_URL_PREFIX file:},
127         * {@code http:}, etc.) will be loaded using the specified resource protocol.
128         * Resource location wildcards (e.g. <code>*&#42;/*.properties</code>)
129         * are not permitted: each location must evaluate to exactly one
130         * {@code .properties} or {@code .xml} resource. Property placeholders
131         * in paths (i.e., <code>${...}</code>) will be
132         * {@linkplain org.springframework.core.env.Environment#resolveRequiredPlaceholders(String) resolved}
133         * against the {@code Environment}.
134         * <h3>Default Properties File Detection</h3>
135         * <p>See the class-level Javadoc for a discussion on detection of defaults.
136         * <h3>Precedence</h3>
137         * <p>Properties loaded from resource locations have lower precedence than
138         * inlined {@link #properties}.
139         * <p>This attribute may <strong>not</strong> be used in conjunction with
140         * {@link #value}, but it may be used <em>instead</em> of {@link #value}.
141         * @see #inheritLocations
142         * @see #value
143         * @see #properties
144         * @see org.springframework.core.env.PropertySource
145         */
146        @AliasFor("value")
147        String[] locations() default {};
148
149        /**
150         * Whether or not test property source {@link #locations} from superclasses
151         * should be <em>inherited</em>.
152         * <p>The default value is {@code true}, which means that a test class will
153         * <em>inherit</em> property source locations defined by a superclass.
154         * Specifically, the property source locations for a test class will be
155         * appended to the list of property source locations defined by a superclass.
156         * Thus, subclasses have the option of <em>extending</em> the list of test
157         * property source locations.
158         * <p>If {@code inheritLocations} is set to {@code false}, the property
159         * source locations for the test class will <em>shadow</em> and effectively
160         * replace any property source locations defined by a superclass.
161         * <p>In the following example, the {@code ApplicationContext} for
162         * {@code BaseTest} will be loaded using only the {@code "base.properties"}
163         * file as a test property source. In contrast, the {@code ApplicationContext}
164         * for {@code ExtendedTest} will be loaded using the {@code "base.properties"}
165         * <strong>and</strong> {@code "extended.properties"} files as test property
166         * source locations.
167         * <pre class="code">
168         * &#064;TestPropertySource(&quot;base.properties&quot;)
169         * &#064;ContextConfiguration
170         * public class BaseTest {
171         *   // ...
172         * }
173         *
174         * &#064;TestPropertySource(&quot;extended.properties&quot;)
175         * &#064;ContextConfiguration
176         * public class ExtendedTest extends BaseTest {
177         *   // ...
178         * }</pre>
179         * <p>If {@code @TestPropertySource} is used as a <em>{@linkplain Repeatable
180         * repeatable}</em> annotation, the following special rules apply.
181         * <ol>
182         * <li>All {@code @TestPropertySource} annotations at a given level in the
183         * test class hierarchy (i.e., directly present or meta-present on a test
184         * class) are considered to be <em>local</em> annotations, in contrast to
185         * {@code @TestPropertySource} annotations that are inherited from a
186         * superclass.</li>
187         * <li>All local {@code @TestPropertySource} annotations must declare the
188         * same value for the {@code inheritLocations} flag.</li>
189         * <li>The {@code inheritLocations} flag is not taken into account between
190         * local {@code @TestPropertySource} annotations. Specifically, the property
191         * source locations for one local annotation will be appended to the list of
192         * property source locations defined by previous local annotations. This
193         * allows a local annotation to extend the list of test property source
194         * locations, potentially overriding individual properties.</li>
195         * </ol>
196         * @see #locations
197         */
198        boolean inheritLocations() default true;
199
200        /**
201         * <em>Inlined properties</em> in the form of <em>key-value</em> pairs that
202         * should be added to the Spring
203         * {@link org.springframework.core.env.Environment Environment} before the
204         * {@code ApplicationContext} is loaded for the test. All key-value pairs
205         * will be added to the enclosing {@code Environment} as a single test
206         * {@code PropertySource} with the highest precedence.
207         * <h3>Supported Syntax</h3>
208         * <p>The supported syntax for key-value pairs is the same as the
209         * syntax defined for entries in a Java
210         * {@linkplain java.util.Properties#load(java.io.Reader) properties file}:
211         * <ul>
212         * <li>{@code "key=value"}</li>
213         * <li>{@code "key:value"}</li>
214         * <li>{@code "key value"}</li>
215         * </ul>
216         * <h3>Precedence</h3>
217         * <p>Properties declared via this attribute have higher precedence than
218         * properties loaded from resource {@link #locations}.
219         * <p>This attribute may be used in conjunction with {@link #value}
220         * <em>or</em> {@link #locations}.
221         * @see #inheritProperties
222         * @see #locations
223         * @see org.springframework.core.env.PropertySource
224         */
225        String[] properties() default {};
226
227        /**
228         * Whether or not inlined test {@link #properties} from superclasses should
229         * be <em>inherited</em>.
230         * <p>The default value is {@code true}, which means that a test class will
231         * <em>inherit</em> inlined properties defined by a superclass. Specifically,
232         * the inlined properties for a test class will be appended to the list of
233         * inlined properties defined by a superclass. Thus, subclasses have the
234         * option of <em>extending</em> the list of inlined test properties.
235         * <p>If {@code inheritProperties} is set to {@code false}, the inlined
236         * properties for the test class will <em>shadow</em> and effectively
237         * replace any inlined properties defined by a superclass.
238         * <p>In the following example, the {@code ApplicationContext} for
239         * {@code BaseTest} will be loaded using only the inlined {@code key1}
240         * property. In contrast, the {@code ApplicationContext} for
241         * {@code ExtendedTest} will be loaded using the inlined {@code key1}
242         * <strong>and</strong> {@code key2} properties.
243         * <pre class="code">
244         * &#064;TestPropertySource(properties = &quot;key1 = value1&quot;)
245         * &#064;ContextConfiguration
246         * public class BaseTest {
247         *   // ...
248         * }
249         * &#064;TestPropertySource(properties = &quot;key2 = value2&quot;)
250         * &#064;ContextConfiguration
251         * public class ExtendedTest extends BaseTest {
252         *   // ...
253         * }</pre>
254         * <p>If {@code @TestPropertySource} is used as a <em>{@linkplain Repeatable
255         * repeatable}</em> annotation, the following special rules apply.
256         * <ol>
257         * <li>All {@code @TestPropertySource} annotations at a given level in the
258         * test class hierarchy (i.e., directly present or meta-present on a test
259         * class) are considered to be <em>local</em> annotations, in contrast to
260         * {@code @TestPropertySource} annotations that are inherited from a
261         * superclass.</li>
262         * <li>All local {@code @TestPropertySource} annotations must declare the
263         * same value for the {@code inheritProperties} flag.</li>
264         * <li>The {@code inheritProperties} flag is not taken into account between
265         * local {@code @TestPropertySource} annotations. Specifically, inlined
266         * properties for one local annotation will be appended to the list of
267         * inlined properties defined by previous local annotations. This allows a
268         * local annotation to extend the list of inlined properties, potentially
269         * overriding individual properties.</li>
270         * </ol>
271         * @see #properties
272         */
273        boolean inheritProperties() default true;
274
275}