org.springframework.test.context.TestPropertySource Maven / Gradle / Ivy
Show all versions of spring-test Show documentation
/*
* Copyright 2002-2023 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
*
* https://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.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.io.support.PropertySourceFactory;
/**
* {@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.
*
* Precedence
* 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}. Note, however, that
* properties registered via {@link DynamicPropertySource @DynamicPropertySource}
* have higher precedence than those loaded via {@code @TestPropertySource}.
*
*
Default Properties File Detection
* If {@code @TestPropertySource} is declared as an empty annotation
* (i.e., without explicit values for {@link #locations} or {@link #properties}),
* an attempt will be made to detect a default 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.
*
*
Enabling @TestPropertySource
* {@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.
*
*
Miscellaneous
*
* - Typically, {@code @TestPropertySource} will be used in conjunction with
* {@link ContextConfiguration @ContextConfiguration}.
* - {@code @TestPropertySource} can be used as a {@linkplain Repeatable
* repeatable} annotation.
* - This annotation may be used as a meta-annotation to create
* custom composed annotations, but 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. Note, however, that ambiguity can be avoided via explicit annotation
* attribute overrides using {@link AliasFor @AliasFor}.
* - As of Spring Framework 5.3, this annotation will be inherited from an
* enclosing test class by default. See
* {@link NestedTestConfiguration @NestedTestConfiguration} for details.
*
*
* @author Sam Brannen
* @since 4.1
* @see ContextConfiguration
* @see DynamicPropertySource
* @see org.springframework.core.env.Environment
* @see org.springframework.core.env.PropertySource
* @see org.springframework.context.annotation.PropertySource
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Repeatable(TestPropertySources.class)
public @interface TestPropertySource {
/**
* Alias for {@link #locations}.
* This attribute may not be used in conjunction with
* {@link #locations}, but it may be used instead 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 (or in the order in which resource
* locations are resolved when location wildcards are used).
*
Supported File Formats
* By default, both traditional and XML-based properties file formats are
* supported — for example, {@code "classpath:/com/example/test.properties"}
* or {@code "file:/path/to/file.xml"}. To support a different file format,
* configure an appropriate {@link #factory() PropertySourceFactory}.
*
Path Resource Semantics
* Each path will be interpreted as a Spring
* {@link org.springframework.core.io.Resource Resource}. A plain path
* — for example, {@code "test.properties"} — will be treated as a
* classpath resource that is relative to the package in which the
* test class is defined. A path starting with a slash will be treated as an
* absolute 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.
*
Property placeholders in paths (i.e., ${...}
) will be
* {@linkplain org.springframework.core.env.Environment#resolveRequiredPlaceholders(String)
* resolved} against the {@code Environment}.
*
As of Spring Framework 6.1, resource location patterns are also
* supported — for example, {@code "classpath*:/config/*.properties"}.
*
WARNING: a pattern such as {@code "classpath*:/config/*.properties"}
* may be effectively equivalent to an explicit enumeration of resource locations such as
* {"classpath:/config/mail.properties", classpath:/config/order.properties"}
;
* however, the two declarations will result in different keys for the context
* cache since the pattern cannot be eagerly resolved to concrete locations.
* Consequently, to benefit from the context cache you must ensure that you
* consistently use either patterns or explicit enumerations of resource
* locations within your test suite.
*
Default Properties File Detection
* See the class-level Javadoc for a discussion on detection of defaults.
*
Precedence
* Properties loaded from resource locations have lower precedence than
* inlined {@link #properties}.
*
This attribute may not be used in conjunction with
* {@link #value}, but it may be used instead of {@link #value}.
* @see #inheritLocations
* @see #value
* @see #properties
* @see #encoding
* @see #factory
* @see org.springframework.core.env.PropertySource
*/
@AliasFor("value")
String[] locations() default {};
/**
* Whether test property source {@link #locations} from superclasses
* and enclosing classes should be inherited.
*
The default value is {@code true}, which means that a test class will
* inherit property source locations defined by a superclass or
* enclosing class. Specifically, the property source locations for a test
* class will be appended to the list of property source locations defined
* by a superclass or enclosing class. Thus, subclasses and nested classes
* have the option of extending the list of test property source
* locations.
*
If {@code inheritLocations} is set to {@code false}, the property
* source locations for the test class will shadow and effectively
* replace any property source locations defined by a superclass or
* enclosing class.
*
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"}
* and {@code "extended.properties"} files as test property
* source locations.
*
* @TestPropertySource("base.properties")
* @ContextConfiguration
* public class BaseTest {
* // ...
* }
*
* @TestPropertySource("extended.properties")
* @ContextConfiguration
* public class ExtendedTest extends BaseTest {
* // ...
* }
* If {@code @TestPropertySource} is used as a {@linkplain Repeatable
* repeatable} annotation, the following special rules apply.
*
* - All {@code @TestPropertySource} annotations at a given level in the
* test class hierarchy (i.e., directly present or meta-present on a test
* class) are considered to be local annotations, in contrast to
* {@code @TestPropertySource} annotations that are inherited from a
* superclass.
* - All local {@code @TestPropertySource} annotations must declare the
* same value for the {@code inheritLocations} flag.
* - The {@code inheritLocations} flag is not taken into account between
* local {@code @TestPropertySource} annotations. Specifically, the property
* source locations for one local annotation will be appended to the list of
* property source locations defined by previous local annotations. This
* allows a local annotation to extend the list of test property source
* locations, potentially overriding individual properties.
*
* @see #locations
*/
boolean inheritLocations() default true;
/**
* Inlined properties in the form of key-value 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. As of Spring Framework
* 6.1, multiple key-value pairs may be specified via a single text block.
* Supported Syntax
* 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}:
*
* - {@code "key=value"}
* - {@code "key:value"}
* - {@code "key value"}
*
* WARNING: although properties can be defined using any
* of the above syntax variants and any number of spaces between the key and
* the value, it is recommended that you use one syntax variant and consistent
* spacing within your test suite — for example, consider always using
* {@code "key = value"} instead of {@code "key= value"}, {@code "key=value"},
* etc. Similarly, if you define inlined properties using text blocks
* you should consistently use text blocks for inlined properties throughout
* your test suite. The reason is that the exact strings you provide will be
* used to determine the key for the context cache. Consequently, to benefit
* from the context cache you must ensure that you define inlined properties
* consistently.
*
Examples
*
* // Using an array of strings
* @TestPropertySource(properties = {
* "key1 = value1",
* "key2 = value2"
* })
* @ContextConfiguration
* class MyTests {
* // ...
* }
*
* // Using a single text block
* @TestPropertySource(properties = """
* key1 = value1
* key2 = value2
* """
* )
* @ContextConfiguration
* class MyTests {
* // ...
* }
* Precedence
* Properties declared via this attribute have higher precedence than
* properties loaded from resource {@link #locations}.
*
This attribute may be used in conjunction with {@link #value}
* or {@link #locations}.
* @see #inheritProperties
* @see #locations
* @see org.springframework.core.env.PropertySource
*/
String[] properties() default {};
/**
* Whether inlined test {@link #properties} from superclasses and
* enclosing classes should be inherited.
*
The default value is {@code true}, which means that a test class will
* inherit inlined properties defined by a superclass or enclosing
* class. Specifically, the inlined properties for a test class will be
* appended to the list of inlined properties defined by a superclass or
* enclosing class. Thus, subclasses and nested classes have the option of
* extending the list of inlined test properties.
*
If {@code inheritProperties} is set to {@code false}, the inlined
* properties for the test class will shadow and effectively
* replace any inlined properties defined by a superclass or enclosing class.
*
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}
* and {@code key2} properties.
*
* @TestPropertySource(properties = "key1 = value1")
* @ContextConfiguration
* public class BaseTest {
* // ...
* }
* @TestPropertySource(properties = "key2 = value2")
* @ContextConfiguration
* public class ExtendedTest extends BaseTest {
* // ...
* }
* If {@code @TestPropertySource} is used as a {@linkplain Repeatable
* repeatable} annotation, the following special rules apply.
*
* - All {@code @TestPropertySource} annotations at a given level in the
* test class hierarchy (i.e., directly present or meta-present on a test
* class) are considered to be local annotations, in contrast to
* {@code @TestPropertySource} annotations that are inherited from a
* superclass or enclosing class.
* - All local {@code @TestPropertySource} annotations must declare the
* same value for the {@code inheritProperties} flag.
* - The {@code inheritProperties} flag is not taken into account between
* local {@code @TestPropertySource} annotations. Specifically, inlined
* properties for one local annotation will be appended to the list of
* inlined properties defined by previous local annotations. This allows a
* local annotation to extend the list of inlined properties, potentially
* overriding individual properties.
*
* @see #properties
*/
boolean inheritProperties() default true;
/**
* Specify the character encoding for the given {@linkplain #locations resources}
* — for example, "UTF-8".
* If not specified, the default character encoding of the JVM will be used.
* @since 6.1
*/
String encoding() default "";
/**
* Specify a custom {@link PropertySourceFactory}, if any.
*
By default, a factory for standard resource files will be used which
* supports {@code *.properties} and {@code *.xml} file formats for
* {@link java.util.Properties}.
* @since 6.1
* @see org.springframework.core.io.support.DefaultPropertySourceFactory
* @see org.springframework.core.io.support.ResourcePropertySource
*/
Class extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}