001/*
002 * Copyright 2002-2016 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.Retention;
023import java.lang.annotation.RetentionPolicy;
024import java.lang.annotation.Target;
025
026import org.springframework.core.annotation.AliasFor;
027
028/**
029 * {@code @TestPropertySource} is a class-level annotation that is used to
030 * configure the {@link #locations} of properties files and inlined
031 * {@link #properties} to be added to the {@code Environment}'s set of
032 * {@code PropertySources} for an
033 * {@link org.springframework.context.ApplicationContext ApplicationContext}
034 * for integration tests.
035 *
036 * <h3>Precedence</h3>
037 * <p>Test property sources have higher precedence than those loaded from the
038 * operating system's environment or Java system properties as well as property
039 * sources added by the application declaratively via
040 * {@link org.springframework.context.annotation.PropertySource @PropertySource}
041 * or programmatically (e.g., via an
042 * {@link org.springframework.context.ApplicationContextInitializer ApplicationContextInitializer}
043 * or some other means). Thus, test property sources can be used to selectively
044 * override properties defined in system and application property sources.
045 * Furthermore, inlined {@link #properties} have higher precedence than
046 * properties loaded from resource {@link #locations}.
047 *
048 * <h3>Default Properties File Detection</h3>
049 * <p>If {@code @TestPropertySource} is declared as an <em>empty</em> annotation
050 * (i.e., without explicit values for {@link #locations} or {@link #properties}),
051 * an attempt will be made to detect a <em>default</em> properties file relative
052 * to the class that declared the annotation. For example, if the annotated test
053 * class is {@code com.example.MyTest}, the corresponding default properties file
054 * is {@code "classpath:com/example/MyTest.properties"}. If the default cannot be
055 * detected, an {@link IllegalStateException} will be thrown.
056 *
057 * <h3>Enabling &#064;TestPropertySource</h3>
058 * <p>{@code @TestPropertySource} is enabled if the configured
059 * {@linkplain ContextConfiguration#loader context loader} honors it. Every
060 * {@code SmartContextLoader} that is a subclass of either
061 * {@link org.springframework.test.context.support.AbstractGenericContextLoader AbstractGenericContextLoader} or
062 * {@link org.springframework.test.context.web.AbstractGenericWebContextLoader AbstractGenericWebContextLoader}
063 * provides automatic support for {@code @TestPropertySource}, and this includes
064 * every {@code SmartContextLoader} provided by the Spring TestContext Framework.
065 *
066 * <h3>Miscellaneous</h3>
067 * <ul>
068 * <li>Typically, {@code @TestPropertySource} will be used in conjunction with
069 * {@link ContextConfiguration @ContextConfiguration}.</li>
070 * <li>This annotation may be used as a <em>meta-annotation</em> to create
071 * custom <em>composed annotations</em>; however, caution should be taken if
072 * this annotation and {@code @ContextConfiguration} are combined on a composed
073 * annotation since the {@code locations} and {@code inheritLocations} attributes
074 * of both annotations can lead to ambiguity during the attribute resolution
075 * process.</li>
076 * </ul>
077 *
078 * @author Sam Brannen
079 * @since 4.1
080 * @see ContextConfiguration
081 * @see org.springframework.core.env.Environment
082 * @see org.springframework.core.env.PropertySource
083 * @see org.springframework.context.annotation.PropertySource
084 */
085@Target(ElementType.TYPE)
086@Retention(RetentionPolicy.RUNTIME)
087@Documented
088@Inherited
089public @interface TestPropertySource {
090
091        /**
092         * Alias for {@link #locations}.
093         * <p>This attribute may <strong>not</strong> be used in conjunction with
094         * {@link #locations}, but it may be used <em>instead</em> of {@link #locations}.
095         * @see #locations
096         */
097        @AliasFor("locations")
098        String[] value() default {};
099
100        /**
101         * The resource locations of properties files to be loaded into the
102         * {@code Environment}'s set of {@code PropertySources}. Each location
103         * will be added to the enclosing {@code Environment} as its own property
104         * source, in the order declared.
105         * <h3>Supported File Formats</h3>
106         * <p>Both traditional and XML-based properties file formats are supported
107         * &mdash; for example, {@code "classpath:/com/example/test.properties"}
108         * or {@code "file:/path/to/file.xml"}.
109         * <h3>Path Resource Semantics</h3>
110         * <p>Each path will be interpreted as a Spring
111         * {@link org.springframework.core.io.Resource Resource}. A plain path
112         * &mdash; for example, {@code "test.properties"} &mdash; will be treated as a
113         * classpath resource that is <em>relative</em> to the package in which the
114         * test class is defined. A path starting with a slash will be treated as an
115         * <em>absolute</em> classpath resource, for example:
116         * {@code "/org/example/test.xml"}. A path which references a
117         * URL (e.g., a path prefixed with
118         * {@link org.springframework.util.ResourceUtils#CLASSPATH_URL_PREFIX classpath:},
119         * {@link org.springframework.util.ResourceUtils#FILE_URL_PREFIX file:},
120         * {@code http:}, etc.) will be loaded using the specified resource protocol.
121         * Resource location wildcards (e.g. <code>*&#42;/*.properties</code>)
122         * are not permitted: each location must evaluate to exactly one
123         * {@code .properties} or {@code .xml} resource. Property placeholders
124         * in paths (i.e., <code>${...}</code>) will be
125         * {@linkplain org.springframework.core.env.Environment#resolveRequiredPlaceholders(String) resolved}
126         * against the {@code Environment}.
127         * <h3>Default Properties File Detection</h3>
128         * <p>See the class-level Javadoc for a discussion on detection of defaults.
129         * <h3>Precedence</h3>
130         * <p>Properties loaded from resource locations have lower precedence than
131         * inlined {@link #properties}.
132         * <p>This attribute may <strong>not</strong> be used in conjunction with
133         * {@link #value}, but it may be used <em>instead</em> of {@link #value}.
134         * @see #inheritLocations
135         * @see #value
136         * @see #properties
137         * @see org.springframework.core.env.PropertySource
138         */
139        @AliasFor("value")
140        String[] locations() default {};
141
142        /**
143         * Whether or not test property source {@link #locations} from superclasses
144         * should be <em>inherited</em>.
145         * <p>The default value is {@code true}, which means that a test class will
146         * <em>inherit</em> property source locations defined by a superclass.
147         * Specifically, the property source locations for a test class will be
148         * appended to the list of property source locations defined by a superclass.
149         * Thus, subclasses have the option of <em>extending</em> the list of test
150         * property source locations.
151         * <p>If {@code inheritLocations} is set to {@code false}, the property
152         * source locations for the test class will <em>shadow</em> and effectively
153         * replace any property source locations defined by a superclass.
154         * <p>In the following example, the {@code ApplicationContext} for
155         * {@code BaseTest} will be loaded using only the {@code "base.properties"}
156         * file as a test property source. In contrast, the {@code ApplicationContext}
157         * for {@code ExtendedTest} will be loaded using the {@code "base.properties"}
158         * <strong>and</strong> {@code "extended.properties"} files as test property
159         * source locations.
160         * <pre class="code">
161         * &#064;TestPropertySource(&quot;base.properties&quot;)
162         * &#064;ContextConfiguration
163         * public class BaseTest {
164         *   // ...
165         * }
166         *
167         * &#064;TestPropertySource(&quot;extended.properties&quot;)
168         * &#064;ContextConfiguration
169         * public class ExtendedTest extends BaseTest {
170         *   // ...
171         * }
172         * </pre>
173         *
174         * @see #locations
175         */
176        boolean inheritLocations() default true;
177
178        /**
179         * <em>Inlined properties</em> in the form of <em>key-value</em> pairs that
180         * should be added to the Spring
181         * {@link org.springframework.core.env.Environment Environment} before the
182         * {@code ApplicationContext} is loaded for the test. All key-value pairs
183         * will be added to the enclosing {@code Environment} as a single test
184         * {@code PropertySource} with the highest precedence.
185         * <h3>Supported Syntax</h3>
186         * <p>The supported syntax for key-value pairs is the same as the
187         * syntax defined for entries in a Java
188         * {@linkplain java.util.Properties#load(java.io.Reader) properties file}:
189         * <ul>
190         * <li>{@code "key=value"}</li>
191         * <li>{@code "key:value"}</li>
192         * <li>{@code "key value"}</li>
193         * </ul>
194         * <h3>Precedence</h3>
195         * <p>Properties declared via this attribute have higher precedence than
196         * properties loaded from resource {@link #locations}.
197         * <p>This attribute may be used in conjunction with {@link #value}
198         * <em>or</em> {@link #locations}.
199         * @see #inheritProperties
200         * @see #locations
201         * @see org.springframework.core.env.PropertySource
202         */
203        String[] properties() default {};
204
205        /**
206         * Whether or not inlined test {@link #properties} from superclasses should
207         * be <em>inherited</em>.
208         * <p>The default value is {@code true}, which means that a test class will
209         * <em>inherit</em> inlined properties defined by a superclass. Specifically,
210         * the inlined properties for a test class will be appended to the list of
211         * inlined properties defined by a superclass. Thus, subclasses have the
212         * option of <em>extending</em> the list of inlined test properties.
213         * <p>If {@code inheritProperties} is set to {@code false}, the inlined
214         * properties for the test class will <em>shadow</em> and effectively
215         * replace any inlined properties defined by a superclass.
216         * <p>In the following example, the {@code ApplicationContext} for
217         * {@code BaseTest} will be loaded using only the inlined {@code key1}
218         * property. In contrast, the {@code ApplicationContext} for
219         * {@code ExtendedTest} will be loaded using the inlined {@code key1}
220         * <strong>and</strong> {@code key2} properties.
221         * <pre class="code">
222         * &#064;TestPropertySource(properties = &quot;key1 = value1&quot;)
223         * &#064;ContextConfiguration
224         * public class BaseTest {
225         *   // ...
226         * }
227         * &#064;TestPropertySource(properties = &quot;key2 = value2&quot;)
228         * &#064;ContextConfiguration
229         * public class ExtendedTest extends BaseTest {
230         *   // ...
231         * }
232         * </pre>
233         * @see #properties
234         */
235        boolean inheritProperties() default true;
236
237}