|
For the latest stable version, please use Spring Framework 6.2.12! |
Context Configuration with Test Property Sources
The Spring Framework has first-class support for the notion of an environment with a
hierarchy of property sources, and you can configure integration tests with test-specific
property sources. In contrast to the @PropertySource annotation used on
@Configuration classes, you can declare the @TestPropertySource annotation on a test
class to declare resource locations for test properties files or inlined properties.
These test property sources are added to the set of PropertySources in the
Environment for the ApplicationContext loaded for the annotated integration test.
|
You can use Implementations of |
Declaring Test Property Sources
You can configure test properties files by using the locations or value attribute of
@TestPropertySource.
By default, both traditional and XML-based java.util.Properties file formats are
supported — for example, "classpath:/com/example/test.properties" or
"file:///path/to/file.xml". As of Spring Framework 6.1, you can configure a custom
PropertySourceFactory via the factory attribute in @TestPropertySource in order to
support a different file format such as JSON, YAML, etc.
Each path is interpreted as a Spring Resource. A plain path (for example,
"test.properties") is treated as a classpath resource that is relative to the package
in which the test class is defined. A path starting with a slash is treated as an
absolute classpath resource (for example: "/org/example/test.xml"). A path that
references a URL (for example, a path prefixed with classpath:, file:, or http:) is
loaded by using the specified resource protocol.
Property placeholders in paths (such as ${…}) will be resolved against the Environment.
As of Spring Framework 6.1, resource location patterns are also supported — for
example, "classpath*:/config/*.properties".
The following example uses a test properties file:
-
Java
-
Kotlin
@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
// class body...
}
| 1 | Specifying a properties file with an absolute path. |
@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
// class body...
}
| 1 | Specifying a properties file with an absolute path. |
You can configure inlined properties in the form of key-value pairs by using the
properties attribute of @TestPropertySource, as shown in the next example. All
key-value pairs are added to the enclosing Environment as a single test
PropertySource with the highest precedence.
The supported syntax for key-value pairs is the same as the syntax defined for entries in a Java properties file:
-
key=value -
key:value -
key value
|
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 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. |
The following example sets two inlined properties:
-
Java
-
Kotlin
@ContextConfiguration
@TestPropertySource(properties = {"timezone = GMT", "port = 4242"}) (1)
class MyIntegrationTests {
// class body...
}
| 1 | Setting two properties via an array of strings. |
@ContextConfiguration
@TestPropertySource(properties = ["timezone = GMT", "port = 4242"]) (1)
class MyIntegrationTests {
// class body...
}
| 1 | Setting two properties via an array of strings. |
As of Spring Framework 6.1, you can use text blocks to define multiple inlined
properties in a single String. The following example sets two inlined properties using
a text block:
-
Java
-
Kotlin
@ContextConfiguration
@TestPropertySource(properties = """
timezone = GMT
port = 4242
""") (1)
class MyIntegrationTests {
// class body...
}
| 1 | Setting two properties via a text block. |
@ContextConfiguration
@TestPropertySource(properties = ["""
timezone = GMT
port = 4242
"""]) (1)
class MyIntegrationTests {
// class body...
}
| 1 | Setting two properties via a text block. |
|
As of Spring Framework 5.2, In addition, you may declare multiple composed annotations on a test class that are each
meta-annotated with Directly present |
Default Properties File Detection
If @TestPropertySource is declared as an empty annotation (that is, without explicit
values for the locations or properties attributes), an attempt is made to detect a
default properties file relative to the class that declared the annotation. For example,
if the annotated test class is com.example.MyTest, the corresponding default properties
file is classpath:com/example/MyTest.properties. If the default cannot be detected, an
IllegalStateException is thrown.
Precedence
Test properties have higher precedence than those defined in the operating system’s
environment, Java system properties, or property sources added by the application
declaratively by using @PropertySource or programmatically. Thus, test properties can
be used to selectively override properties loaded from system and application property
sources. Furthermore, inlined properties have higher precedence than properties loaded
from resource locations. Note, however, that properties registered via
@DynamicPropertySource have
higher precedence than those loaded via @TestPropertySource.
In the next example, the timezone and port properties and any properties defined in
"/test.properties" override any properties of the same name that are defined in system
and application property sources. Furthermore, if the "/test.properties" file defines
entries for the timezone and port properties those are overridden by the inlined
properties declared by using the properties attribute. The following example shows how
to specify properties both in a file and inline:
-
Java
-
Kotlin
@ContextConfiguration
@TestPropertySource(
locations = "/test.properties",
properties = {"timezone = GMT", "port = 4242"}
)
class MyIntegrationTests {
// class body...
}
@ContextConfiguration
@TestPropertySource("/test.properties",
properties = ["timezone = GMT", "port = 4242"]
)
class MyIntegrationTests {
// class body...
}
Inheriting and Overriding Test Property Sources
@TestPropertySource supports boolean inheritLocations and inheritProperties
attributes that denote whether resource locations for properties files and inlined
properties declared by superclasses should be inherited. The default value for both flags
is true. This means that a test class inherits the locations and inlined properties
declared by any superclasses. Specifically, the locations and inlined properties for a
test class are appended to the locations and inlined properties declared by superclasses.
Thus, subclasses have the option of extending the locations and inlined properties. Note
that properties that appear later shadow (that is, override) properties of the same name
that appear earlier. In addition, the aforementioned precedence rules apply for inherited
test property sources as well.
If the inheritLocations or inheritProperties attribute in @TestPropertySource is
set to false, the locations or inlined properties, respectively, for the test class
shadow and effectively replace the configuration defined by superclasses.
As of Spring Framework 5.3, test configuration may also be inherited from enclosing
classes. See @Nested test class configuration for details.
|
In the next example, the ApplicationContext for BaseTest is loaded by using only the
base.properties file as a test property source. In contrast, the ApplicationContext
for ExtendedTest is loaded by using the base.properties and extended.properties
files as test property source locations. The following example shows how to define
properties in both a subclass and its superclass by using properties files:
-
Java
-
Kotlin
@TestPropertySource("base.properties")
@ContextConfiguration
class BaseTest {
// ...
}
@TestPropertySource("extended.properties")
@ContextConfiguration
class ExtendedTest extends BaseTest {
// ...
}
@TestPropertySource("base.properties")
@ContextConfiguration
open class BaseTest {
// ...
}
@TestPropertySource("extended.properties")
@ContextConfiguration
class ExtendedTest : BaseTest() {
// ...
}
In the next example, the ApplicationContext for BaseTest is loaded by using only the
inlined key1 property. In contrast, the ApplicationContext for ExtendedTest is
loaded by using the inlined key1 and key2 properties. The following example shows how
to define properties in both a subclass and its superclass by using inline properties:
-
Java
-
Kotlin
@TestPropertySource(properties = "key1 = value1")
@ContextConfiguration
class BaseTest {
// ...
}
@TestPropertySource(properties = "key2 = value2")
@ContextConfiguration
class ExtendedTest extends BaseTest {
// ...
}
@TestPropertySource(properties = ["key1 = value1"])
@ContextConfiguration
open class BaseTest {
// ...
}
@TestPropertySource(properties = ["key2 = value2"])
@ContextConfiguration
class ExtendedTest : BaseTest() {
// ...
}