This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Framework 6.2.0! |
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. |
That means that you can have multiple declarations of 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.
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() {
// ...
}