This section covers annotations that you can use when you test Spring applications. It includes the following topics:
The following annotations are supported with standard semantics for all configurations of the Spring TestContext Framework. Note that these annotations are not specific to tests and can be used anywhere in the Spring Framework.
-
@Autowired
-
@Qualifier
-
@Value
-
@Resource
(jakarta.annotation) if JSR-250 is present -
@ManagedBean
(jakarta.annotation) if JSR-250 is present -
@Inject
(jakarta.inject) if JSR-330 is present -
@Named
(jakarta.inject) if JSR-330 is present -
@PersistenceContext
(jakarta.persistence) if JPA is present -
@PersistenceUnit
(jakarta.persistence) if JPA is present -
@Transactional
(org.springframework.transaction.annotation) with limited attribute support
Note
|
JSR-250 Lifecycle Annotations
In the Spring TestContext Framework, you can use If a method within a test class is annotated with |
The Spring Framework provides the following set of Spring-specific annotations that you can use in your unit and integration tests in conjunction with the TestContext framework. See the corresponding javadoc for further information, including default attribute values, attribute aliases, and other details.
Spring’s testing annotations include the following:
@BootstrapWith
is a class-level annotation that you can use to configure how the Spring
TestContext Framework is bootstrapped. Specifically, you can use @BootstrapWith
to
specify a custom TestContextBootstrapper
. See the section on
bootstrapping the TestContext framework for further details.
@ContextConfiguration
defines class-level metadata that is used to determine how to
load and configure an ApplicationContext
for integration tests. Specifically,
@ContextConfiguration
declares the application context resource locations
or the
component classes
used to load the context.
Resource locations are typically XML configuration files or Groovy scripts located in the
classpath, while component classes are typically @Configuration
classes. However,
resource locations can also refer to files and scripts in the file system, and component
classes can be @Component
classes, @Service
classes, and so on. See
[testcontext-ctx-management-javaconfig-component-classes] for further details.
The following example shows a @ContextConfiguration
annotation that refers to an XML
file:
@ContextConfiguration("/test-config.xml") // (1)
class XmlApplicationContextTests {
// class body...
}
-
Referring to an XML file.
@ContextConfiguration("/test-config.xml") // (1)
class XmlApplicationContextTests {
// class body...
}
-
Referring to an XML file.
The following example shows a @ContextConfiguration
annotation that refers to a class:
@ContextConfiguration(classes = TestConfig.class) // (1)
class ConfigClassApplicationContextTests {
// class body...
}
-
Referring to a class.
@ContextConfiguration(classes = [TestConfig::class]) // (1)
class ConfigClassApplicationContextTests {
// class body...
}
-
Referring to a class.
As an alternative or in addition to declaring resource locations or component classes,
you can use @ContextConfiguration
to declare ApplicationContextInitializer
classes.
The following example shows such a case:
@ContextConfiguration(initializers = CustomContextInitializer.class) // (1)
class ContextInitializerTests {
// class body...
}
-
Declaring an initializer class.
@ContextConfiguration(initializers = [CustomContextInitializer::class]) // (1)
class ContextInitializerTests {
// class body...
}
-
Declaring an initializer class.
You can optionally use @ContextConfiguration
to declare the ContextLoader
strategy as
well. Note, however, that you typically do not need to explicitly configure the loader,
since the default loader supports initializers
and either resource locations
or
component classes
.
The following example uses both a location and a loader:
@ContextConfiguration(locations = "/test-context.xml", loader = CustomContextLoader.class) // (1)
class CustomLoaderXmlApplicationContextTests {
// class body...
}
-
Configuring both a location and a custom loader.
@ContextConfiguration("/test-context.xml", loader = CustomContextLoader::class) // (1)
class CustomLoaderXmlApplicationContextTests {
// class body...
}
-
Configuring both a location and a custom loader.
Note
|
@ContextConfiguration provides support for inheriting resource locations or
configuration classes as well as context initializers that are declared by superclasses
or enclosing classes.
|
See [testcontext-ctx-management],
[testcontext-junit-jupiter-nested-test-configuration], and the @ContextConfiguration
javadocs for further details.
@WebAppConfiguration
is a class-level annotation that you can use to declare that the
ApplicationContext
loaded for an integration test should be a WebApplicationContext
.
The mere presence of @WebAppConfiguration
on a test class ensures that a
WebApplicationContext
is loaded for the test, using the default value of
"file:src/main/webapp"
for the path to the root of the web application (that is, the
resource base path). The resource base path is used behind the scenes to create a
MockServletContext
, which serves as the ServletContext
for the test’s
WebApplicationContext
.
The following example shows how to use the @WebAppConfiguration
annotation:
@ContextConfiguration
@WebAppConfiguration // (1)
class WebAppTests {
// class body...
}
-
The
@WebAppConfiguration
annotation.
@ContextConfiguration
@WebAppConfiguration // (1)
class WebAppTests {
// class body...
}
-
The
@WebAppConfiguration
annotation.
To override the default, you can specify a different base resource path by using the
implicit value
attribute. Both classpath:
and file:
resource prefixes are
supported. If no resource prefix is supplied, the path is assumed to be a file system
resource. The following example shows how to specify a classpath resource:
@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources") // (1)
class WebAppTests {
// class body...
}
-
Specifying a classpath resource.
@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources") // (1)
class WebAppTests {
// class body...
}
-
Specifying a classpath resource.
Note that @WebAppConfiguration
must be used in conjunction with
@ContextConfiguration
, either within a single test class or within a test class
hierarchy. See the
{api-spring-framework}/test/context/web/WebAppConfiguration.html[@WebAppConfiguration
]
javadoc for further details.
@ContextHierarchy
is a class-level annotation that is used to define a hierarchy of
ApplicationContext
instances for integration tests. @ContextHierarchy
should be
declared with a list of one or more @ContextConfiguration
instances, each of which
defines a level in the context hierarchy. The following examples demonstrate the use of
@ContextHierarchy
within a single test class (@ContextHierarchy
can also be used
within a test class hierarchy):
@ContextHierarchy({
@ContextConfiguration("/parent-config.xml"),
@ContextConfiguration("/child-config.xml")
})
class ContextHierarchyTests {
// class body...
}
@ContextHierarchy(
ContextConfiguration("/parent-config.xml"),
ContextConfiguration("/child-config.xml"))
class ContextHierarchyTests {
// class body...
}
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration(classes = AppConfig.class),
@ContextConfiguration(classes = WebConfig.class)
})
class WebIntegrationTests {
// class body...
}
@WebAppConfiguration
@ContextHierarchy(
ContextConfiguration(classes = [AppConfig::class]),
ContextConfiguration(classes = [WebConfig::class]))
class WebIntegrationTests {
// class body...
}
If you need to merge or override the configuration for a given level of the context
hierarchy within a test class hierarchy, you must explicitly name that level by supplying
the same value to the name
attribute in @ContextConfiguration
at each corresponding
level in the class hierarchy. See [testcontext-ctx-management-ctx-hierarchies] and the
{api-spring-framework}/test/context/ContextHierarchy.html[@ContextHierarchy
] javadoc
for further examples.
@ActiveProfiles
is a class-level annotation that is used to declare which bean
definition profiles should be active when loading an ApplicationContext
for an
integration test.
The following example indicates that the dev
profile should be active:
@ContextConfiguration
@ActiveProfiles("dev") // (1)
class DeveloperTests {
// class body...
}
-
Indicate that the
dev
profile should be active.
@ContextConfiguration
@ActiveProfiles("dev") // (1)
class DeveloperTests {
// class body...
}
-
Indicate that the
dev
profile should be active.
The following example indicates that both the dev
and the integration
profiles should
be active:
@ContextConfiguration
@ActiveProfiles({"dev", "integration"}) // (1)
class DeveloperIntegrationTests {
// class body...
}
-
Indicate that the
dev
andintegration
profiles should be active.
@ContextConfiguration
@ActiveProfiles(["dev", "integration"]) // (1)
class DeveloperIntegrationTests {
// class body...
}
-
Indicate that the
dev
andintegration
profiles should be active.
Note
|
@ActiveProfiles provides support for inheriting active bean definition profiles
declared by superclasses and enclosing classes by default. You can also resolve active
bean definition profiles programmatically by implementing a custom
ActiveProfilesResolver
and registering it by using the resolver attribute of @ActiveProfiles .
|
See [testcontext-ctx-management-env-profiles],
[testcontext-junit-jupiter-nested-test-configuration], and the
{api-spring-framework}/test/context/ActiveProfiles.html[@ActiveProfiles
] javadoc for
examples and further details.
@TestPropertySource
is a class-level annotation that you can use to configure the
locations of properties files and inlined properties to be added to the set of
PropertySources
in the Environment
for an ApplicationContext
loaded for an
integration test.
The following example demonstrates how to declare a properties file from the classpath:
@ContextConfiguration
@TestPropertySource("/test.properties") // (1)
class MyIntegrationTests {
// class body...
}
-
Get properties from
test.properties
in the root of the classpath.
@ContextConfiguration
@TestPropertySource("/test.properties") // (1)
class MyIntegrationTests {
// class body...
}
-
Get properties from
test.properties
in the root of the classpath.
The following example demonstrates how to declare inlined properties:
@ContextConfiguration
@TestPropertySource(properties = { "timezone = GMT", "port: 4242" }) // (1)
class MyIntegrationTests {
// class body...
}
-
Declare
timezone
andport
properties.
@ContextConfiguration
@TestPropertySource(properties = ["timezone = GMT", "port: 4242"]) // (1)
class MyIntegrationTests {
// class body...
}
-
Declare
timezone
andport
properties.
See [testcontext-ctx-management-property-sources] for examples and further details.
@DynamicPropertySource
is a method-level annotation that you can use to register
dynamic properties to be added to the set of PropertySources
in the Environment
for
an ApplicationContext
loaded for an integration test. Dynamic properties are useful
when you do not know the value of the properties upfront – for example, if the properties
are managed by an external resource such as for a container managed by the
Testcontainers project.
The following example demonstrates how to register a dynamic property:
@ContextConfiguration
class MyIntegrationTests {
static MyExternalServer server = // ...
@DynamicPropertySource // (1)
static void dynamicProperties(DynamicPropertyRegistry registry) { // (2)
registry.add("server.port", server::getPort); // (3)
}
// tests ...
}
-
Annotate a
static
method with@DynamicPropertySource
. -
Accept a
DynamicPropertyRegistry
as an argument. -
Register a dynamic
server.port
property to be retrieved lazily from the server.
@ContextConfiguration
class MyIntegrationTests {
companion object {
@JvmStatic
val server: MyExternalServer = // ...
@DynamicPropertySource // (1)
@JvmStatic
fun dynamicProperties(registry: DynamicPropertyRegistry) { // (2)
registry.add("server.port", server::getPort) // (3)
}
}
// tests ...
}
-
Annotate a
static
method with@DynamicPropertySource
. -
Accept a
DynamicPropertyRegistry
as an argument. -
Register a dynamic
server.port
property to be retrieved lazily from the server.
See [testcontext-ctx-management-dynamic-property-sources] for further details.
@DirtiesContext
indicates that the underlying Spring ApplicationContext
has been
dirtied during the execution of a test (that is, the test modified or corrupted it in
some manner — for example, by changing the state of a singleton bean) and should be
closed. When an application context is marked as dirty, it is removed from the testing
framework’s cache and closed. As a consequence, the underlying Spring container is
rebuilt for any subsequent test that requires a context with the same configuration
metadata.
You can use @DirtiesContext
as both a class-level and a method-level annotation within
the same class or class hierarchy. In such scenarios, the ApplicationContext
is marked
as dirty before or after any such annotated method as well as before or after the current
test class, depending on the configured methodMode
and classMode
.
The following examples explain when the context would be dirtied for various configuration scenarios:
-
Before the current test class, when declared on a class with class mode set to
BEFORE_CLASS
.Java@DirtiesContext(classMode = BEFORE_CLASS) // (1) class FreshContextTests { // some tests that require a new Spring container }
-
Dirty the context before the current test class.
Kotlin@DirtiesContext(classMode = BEFORE_CLASS) // (1) class FreshContextTests { // some tests that require a new Spring container }
-
Dirty the context before the current test class.
-
-
After the current test class, when declared on a class with class mode set to
AFTER_CLASS
(i.e., the default class mode).Java@DirtiesContext // (1) class ContextDirtyingTests { // some tests that result in the Spring container being dirtied }
-
Dirty the context after the current test class.
Kotlin@DirtiesContext // (1) class ContextDirtyingTests { // some tests that result in the Spring container being dirtied }
-
Dirty the context after the current test class.
-
-
Before each test method in the current test class, when declared on a class with class mode set to
BEFORE_EACH_TEST_METHOD.
Java@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD) // (1) class FreshContextTests { // some tests that require a new Spring container }
-
Dirty the context before each test method.
Kotlin@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD) // (1) class FreshContextTests { // some tests that require a new Spring container }
-
Dirty the context before each test method.
-
-
After each test method in the current test class, when declared on a class with class mode set to
AFTER_EACH_TEST_METHOD.
Java@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) // (1) class ContextDirtyingTests { // some tests that result in the Spring container being dirtied }
-
Dirty the context after each test method.
Kotlin@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) // (1) class ContextDirtyingTests { // some tests that result in the Spring container being dirtied }
-
Dirty the context after each test method.
-
-
Before the current test, when declared on a method with the method mode set to
BEFORE_METHOD
.Java@DirtiesContext(methodMode = BEFORE_METHOD) // (1) @Test void testProcessWhichRequiresFreshAppCtx() { // some logic that requires a new Spring container }
-
Dirty the context before the current test method.
Kotlin@DirtiesContext(methodMode = BEFORE_METHOD) // (1) @Test fun testProcessWhichRequiresFreshAppCtx() { // some logic that requires a new Spring container }
-
Dirty the context before the current test method.
-
-
After the current test, when declared on a method with the method mode set to
AFTER_METHOD
(i.e., the default method mode).Java@DirtiesContext // (1) @Test void testProcessWhichDirtiesAppCtx() { // some logic that results in the Spring container being dirtied }
-
Dirty the context after the current test method.
Kotlin@DirtiesContext // (1) @Test fun testProcessWhichDirtiesAppCtx() { // some logic that results in the Spring container being dirtied }
-
Dirty the context after the current test method.
-
If you use @DirtiesContext
in a test whose context is configured as part of a context
hierarchy with @ContextHierarchy
, you can use the hierarchyMode
flag to control how
the context cache is cleared. By default, an exhaustive algorithm is used to clear the
context cache, including not only the current level but also all other context
hierarchies that share an ancestor context common to the current test. All
ApplicationContext
instances that reside in a sub-hierarchy of the common ancestor
context are removed from the context cache and closed. If the exhaustive algorithm is
overkill for a particular use case, you can specify the simpler current level algorithm,
as the following example shows.
@ContextHierarchy({
@ContextConfiguration("/parent-config.xml"),
@ContextConfiguration("/child-config.xml")
})
class BaseTests {
// class body...
}
class ExtendedTests extends BaseTests {
@Test
@DirtiesContext(hierarchyMode = CURRENT_LEVEL) // (1)
void test() {
// some logic that results in the child context being dirtied
}
}
-
Use the current-level algorithm.
@ContextHierarchy(
ContextConfiguration("/parent-config.xml"),
ContextConfiguration("/child-config.xml"))
open class BaseTests {
// class body...
}
class ExtendedTests : BaseTests() {
@Test
@DirtiesContext(hierarchyMode = CURRENT_LEVEL) // (1)
fun test() {
// some logic that results in the child context being dirtied
}
}
-
Use the current-level algorithm.
For further details regarding the EXHAUSTIVE
and CURRENT_LEVEL
algorithms, see the
{api-spring-framework}/test/annotation/DirtiesContext.HierarchyMode.html[DirtiesContext.HierarchyMode
]
javadoc.
@TestExecutionListeners
is used to register listeners for a particular test class, its
subclasses, and its nested classes. If you wish to register a listener globally, you
should register it via the automatic discovery mechanism described in
[testcontext-tel-config].
The following example shows how to register two TestExecutionListener
implementations:
@ContextConfiguration
@TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class}) // (1)
class CustomTestExecutionListenerTests {
// class body...
}
-
Register two
TestExecutionListener
implementations.
@ContextConfiguration
@TestExecutionListeners(CustomTestExecutionListener::class, AnotherTestExecutionListener::class) // (1)
class CustomTestExecutionListenerTests {
// class body...
}
-
Register two
TestExecutionListener
implementations.
By default, @TestExecutionListeners
provides support for inheriting listeners from
superclasses or enclosing classes. See
[testcontext-junit-jupiter-nested-test-configuration] and the
{api-spring-framework}/test/context/TestExecutionListeners.html[@TestExecutionListeners
javadoc] for an example and further details. If you discover that you need to switch
back to using the default TestExecutionListener
implementations, see the note
in [testcontext-tel-config-registering-tels].
@RecordApplicationEvents
is a class-level annotation that is used to instruct the
Spring TestContext Framework to record all application events that are published in the
ApplicationContext
during the execution of a single test.
The recorded events can be accessed via the ApplicationEvents
API within tests.
See [testcontext-application-events] and the
{api-spring-framework}/test/context/event/RecordApplicationEvents.html[@RecordApplicationEvents
javadoc] for an example and further details.
@Commit
indicates that the transaction for a transactional test method should be
committed after the test method has completed. You can use @Commit
as a direct
replacement for @Rollback(false)
to more explicitly convey the intent of the code.
Analogous to @Rollback
, @Commit
can also be declared as a class-level or method-level
annotation.
The following example shows how to use the @Commit
annotation:
@Commit // (1)
@Test
void testProcessWithoutRollback() {
// ...
}
-
Commit the result of the test to the database.
@Commit // (1)
@Test
fun testProcessWithoutRollback() {
// ...
}
-
Commit the result of the test to the database.
@Rollback
indicates whether the transaction for a transactional test method should be
rolled back after the test method has completed. If true
, the transaction is rolled
back. Otherwise, the transaction is committed (see also
@Commit
). Rollback for integration tests in the Spring
TestContext Framework defaults to true
even if @Rollback
is not explicitly declared.
When declared as a class-level annotation, @Rollback
defines the default rollback
semantics for all test methods within the test class hierarchy. When declared as a
method-level annotation, @Rollback
defines rollback semantics for the specific test
method, potentially overriding class-level @Rollback
or @Commit
semantics.
The following example causes a test method’s result to not be rolled back (that is, the result is committed to the database):
@Rollback(false) // (1)
@Test
void testProcessWithoutRollback() {
// ...
}
-
Do not roll back the result.
@Rollback(false) // (1)
@Test
fun testProcessWithoutRollback() {
// ...
}
-
Do not roll back the result.
@BeforeTransaction
indicates that the annotated void
method should be run before a
transaction is started, for test methods that have been configured to run within a
transaction by using Spring’s @Transactional
annotation. @BeforeTransaction
methods
are not required to be public
and may be declared on Java 8-based interface default
methods.
The following example shows how to use the @BeforeTransaction
annotation:
@BeforeTransaction // (1)
void beforeTransaction() {
// logic to be run before a transaction is started
}
-
Run this method before a transaction.
@BeforeTransaction // (1)
fun beforeTransaction() {
// logic to be run before a transaction is started
}
-
Run this method before a transaction.
@AfterTransaction
indicates that the annotated void
method should be run after a
transaction is ended, for test methods that have been configured to run within a
transaction by using Spring’s @Transactional
annotation. @AfterTransaction
methods
are not required to be public
and may be declared on Java 8-based interface default
methods.
@AfterTransaction // (1)
void afterTransaction() {
// logic to be run after a transaction has ended
}
-
Run this method after a transaction.
@AfterTransaction // (1)
fun afterTransaction() {
// logic to be run after a transaction has ended
}
-
Run this method after a transaction.
@Sql
is used to annotate a test class or test method to configure SQL scripts to be run
against a given database during integration tests. The following example shows how to use
it:
@Test
@Sql({"/test-schema.sql", "/test-user-data.sql"}) // (1)
void userTest() {
// run code that relies on the test schema and test data
}
-
Run two scripts for this test.
@Test
@Sql("/test-schema.sql", "/test-user-data.sql") // (1)
fun userTest() {
// run code that relies on the test schema and test data
}
-
Run two scripts for this test.
See [testcontext-executing-sql-declaratively] for further details.
@SqlConfig
defines metadata that is used to determine how to parse and run SQL scripts
configured with the @Sql
annotation. The following example shows how to use it:
@Test
@Sql(
scripts = "/test-user-data.sql",
config = @SqlConfig(commentPrefix = "`", separator = "@@") // (1)
)
void userTest() {
// run code that relies on the test data
}
-
Set the comment prefix and the separator in SQL scripts.
@Test
@Sql("/test-user-data.sql", config = SqlConfig(commentPrefix = "`", separator = "@@")) // (1)
fun userTest() {
// run code that relies on the test data
}
-
Set the comment prefix and the separator in SQL scripts.
@SqlMergeMode
is used to annotate a test class or test method to configure whether
method-level @Sql
declarations are merged with class-level @Sql
declarations. If
@SqlMergeMode
is not declared on a test class or test method, the OVERRIDE
merge mode
will be used by default. With the OVERRIDE
mode, method-level @Sql
declarations will
effectively override class-level @Sql
declarations.
Note that a method-level @SqlMergeMode
declaration overrides a class-level declaration.
The following example shows how to use @SqlMergeMode
at the class level.
@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
@SqlMergeMode(MERGE) // (1)
class UserTests {
@Test
@Sql("/user-test-data-001.sql")
void standardUserProfile() {
// run code that relies on test data set 001
}
}
-
Set the
@Sql
merge mode toMERGE
for all test methods in the class.
@SpringJUnitConfig(TestConfig::class)
@Sql("/test-schema.sql")
@SqlMergeMode(MERGE) // (1)
class UserTests {
@Test
@Sql("/user-test-data-001.sql")
fun standardUserProfile() {
// run code that relies on test data set 001
}
}
-
Set the
@Sql
merge mode toMERGE
for all test methods in the class.
The following example shows how to use @SqlMergeMode
at the method level.
@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
class UserTests {
@Test
@Sql("/user-test-data-001.sql")
@SqlMergeMode(MERGE) // (1)
void standardUserProfile() {
// run code that relies on test data set 001
}
}
-
Set the
@Sql
merge mode toMERGE
for a specific test method.
@SpringJUnitConfig(TestConfig::class)
@Sql("/test-schema.sql")
class UserTests {
@Test
@Sql("/user-test-data-001.sql")
@SqlMergeMode(MERGE) // (1)
fun standardUserProfile() {
// run code that relies on test data set 001
}
}
-
Set the
@Sql
merge mode toMERGE
for a specific test method.
@SqlGroup
is a container annotation that aggregates several @Sql
annotations. You can
use @SqlGroup
natively to declare several nested @Sql
annotations, or you can use it
in conjunction with Java 8’s support for repeatable annotations, where @Sql
can be
declared several times on the same class or method, implicitly generating this container
annotation. The following example shows how to declare an SQL group:
@Test
@SqlGroup({ // (1)
@Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")),
@Sql("/test-user-data.sql")
})
void userTest() {
// run code that uses the test schema and test data
}
-
Declare a group of SQL scripts.
@Test
@SqlGroup( // (1)
Sql("/test-schema.sql", config = SqlConfig(commentPrefix = "`")),
Sql("/test-user-data.sql"))
fun userTest() {
// run code that uses the test schema and test data
}
-
Declare a group of SQL scripts.
The following annotations are supported only when used in conjunction with the SpringRunner, Spring’s JUnit 4 rules, or Spring’s JUnit 4 support classes:
@IfProfileValue
indicates that the annotated test is enabled for a specific testing
environment. If the configured ProfileValueSource
returns a matching value
for the
provided name
, the test is enabled. Otherwise, the test is disabled and, effectively,
ignored.
You can apply @IfProfileValue
at the class level, the method level, or both.
Class-level usage of @IfProfileValue
takes precedence over method-level usage for any
methods within that class or its subclasses. Specifically, a test is enabled if it is
enabled both at the class level and at the method level. The absence of @IfProfileValue
means the test is implicitly enabled. This is analogous to the semantics of JUnit 4’s
@Ignore
annotation, except that the presence of @Ignore
always disables a test.
The following example shows a test that has an @IfProfileValue
annotation:
@IfProfileValue(name="java.vendor", value="Oracle Corporation") // (1)
@Test
public void testProcessWhichRunsOnlyOnOracleJvm() {
// some logic that should run only on Java VMs from Oracle Corporation
}
-
Run this test only when the Java vendor is "Oracle Corporation".
@IfProfileValue(name="java.vendor", value="Oracle Corporation") // (1)
@Test
fun testProcessWhichRunsOnlyOnOracleJvm() {
// some logic that should run only on Java VMs from Oracle Corporation
}
-
Run this test only when the Java vendor is "Oracle Corporation".
Alternatively, you can configure @IfProfileValue
with a list of values
(with OR
semantics) to achieve TestNG-like support for test groups in a JUnit 4 environment.
Consider the following example:
@IfProfileValue(name="test-groups", values={"unit-tests", "integration-tests"}) // (1)
@Test
public void testProcessWhichRunsForUnitOrIntegrationTestGroups() {
// some logic that should run only for unit and integration test groups
}
-
Run this test for unit tests and integration tests.
@IfProfileValue(name="test-groups", values=["unit-tests", "integration-tests"]) // (1)
@Test
fun testProcessWhichRunsForUnitOrIntegrationTestGroups() {
// some logic that should run only for unit and integration test groups
}
-
Run this test for unit tests and integration tests.
@ProfileValueSourceConfiguration
is a class-level annotation that specifies what type
of ProfileValueSource
to use when retrieving profile values configured through the
@IfProfileValue
annotation. If @ProfileValueSourceConfiguration
is not declared for a
test, SystemProfileValueSource
is used by default. The following example shows how to
use @ProfileValueSourceConfiguration
:
@ProfileValueSourceConfiguration(CustomProfileValueSource.class) // (1)
public class CustomProfileValueSourceTests {
// class body...
}
-
Use a custom profile value source.
@ProfileValueSourceConfiguration(CustomProfileValueSource::class) // (1)
class CustomProfileValueSourceTests {
// class body...
}
-
Use a custom profile value source.
@Timed
indicates that the annotated test method must finish execution in a specified
time period (in milliseconds). If the text execution time exceeds the specified time
period, the test fails.
The time period includes running the test method itself, any repetitions of the test (see
@Repeat
), as well as any setting up or tearing down of the test fixture. The following
example shows how to use it:
@Timed(millis = 1000) // (1)
public void testProcessWithOneSecondTimeout() {
// some logic that should not take longer than 1 second to run
}
-
Set the time period for the test to one second.
@Timed(millis = 1000) // (1)
fun testProcessWithOneSecondTimeout() {
// some logic that should not take longer than 1 second to run
}
-
Set the time period for the test to one second.
Spring’s @Timed
annotation has different semantics than JUnit 4’s @Test(timeout=…)
support. Specifically, due to the manner in which JUnit 4 handles test execution timeouts
(that is, by executing the test method in a separate Thread
), @Test(timeout=…)
preemptively fails the test if the test takes too long. Spring’s @Timed
, on the other
hand, does not preemptively fail the test but rather waits for the test to complete
before failing.
@Repeat
indicates that the annotated test method must be run repeatedly. The number of
times that the test method is to be run is specified in the annotation.
The scope of execution to be repeated includes execution of the test method itself as
well as any setting up or tearing down of the test fixture. When used with the
SpringMethodRule
, the scope additionally includes
preparation of the test instance by TestExecutionListener
implementations. The
following example shows how to use the @Repeat
annotation:
@Repeat(10) // (1)
@Test
public void testProcessRepeatedly() {
// ...
}
-
Repeat this test ten times.
@Repeat(10) // (1)
@Test
fun testProcessRepeatedly() {
// ...
}
-
Repeat this test ten times.
The following annotations are supported when used in conjunction with the
SpringExtension
and JUnit Jupiter
(that is, the programming model in JUnit 5):
@SpringJUnitConfig
is a composed annotation that combines
@ExtendWith(SpringExtension.class)
from JUnit Jupiter with @ContextConfiguration
from
the Spring TestContext Framework. It can be used at the class level as a drop-in
replacement for @ContextConfiguration
. With regard to configuration options, the only
difference between @ContextConfiguration
and @SpringJUnitConfig
is that component
classes may be declared with the value
attribute in @SpringJUnitConfig
.
The following example shows how to use the @SpringJUnitConfig
annotation to specify a
configuration class:
@SpringJUnitConfig(TestConfig.class) // (1)
class ConfigurationClassJUnitJupiterSpringTests {
// class body...
}
-
Specify the configuration class.
@SpringJUnitConfig(TestConfig::class) // (1)
class ConfigurationClassJUnitJupiterSpringTests {
// class body...
}
-
Specify the configuration class.
The following example shows how to use the @SpringJUnitConfig
annotation to specify the
location of a configuration file:
@SpringJUnitConfig(locations = "/test-config.xml") // (1)
class XmlJUnitJupiterSpringTests {
// class body...
}
-
Specify the location of a configuration file.
@SpringJUnitConfig(locations = ["/test-config.xml"]) // (1)
class XmlJUnitJupiterSpringTests {
// class body...
}
-
Specify the location of a configuration file.
See [testcontext-ctx-management] as well as the javadoc for
{api-spring-framework}/test/context/junit/jupiter/SpringJUnitConfig.html[@SpringJUnitConfig
]
and @ContextConfiguration
for further details.
@SpringJUnitWebConfig
is a composed annotation that combines
@ExtendWith(SpringExtension.class)
from JUnit Jupiter with @ContextConfiguration
and
@WebAppConfiguration
from the Spring TestContext Framework. You can use it at the class
level as a drop-in replacement for @ContextConfiguration
and @WebAppConfiguration
.
With regard to configuration options, the only difference between @ContextConfiguration
and @SpringJUnitWebConfig
is that you can declare component classes by using the
value
attribute in @SpringJUnitWebConfig
. In addition, you can override the value
attribute from @WebAppConfiguration
only by using the resourcePath
attribute in
@SpringJUnitWebConfig
.
The following example shows how to use the @SpringJUnitWebConfig
annotation to specify
a configuration class:
@SpringJUnitWebConfig(TestConfig.class) // (1)
class ConfigurationClassJUnitJupiterSpringWebTests {
// class body...
}
-
Specify the configuration class.
@SpringJUnitWebConfig(TestConfig::class) // (1)
class ConfigurationClassJUnitJupiterSpringWebTests {
// class body...
}
-
Specify the configuration class.
The following example shows how to use the @SpringJUnitWebConfig
annotation to specify the
location of a configuration file:
@SpringJUnitWebConfig(locations = "/test-config.xml") // (1)
class XmlJUnitJupiterSpringWebTests {
// class body...
}
-
Specify the location of a configuration file.
@SpringJUnitWebConfig(locations = ["/test-config.xml"]) // (1)
class XmlJUnitJupiterSpringWebTests {
// class body...
}
-
Specify the location of a configuration file.
See [testcontext-ctx-management] as well as the javadoc for
{api-spring-framework}/test/context/junit/jupiter/web/SpringJUnitWebConfig.html[@SpringJUnitWebConfig
],
{api-spring-framework}/test/context/ContextConfiguration.html[@ContextConfiguration
], and
{api-spring-framework}/test/context/web/WebAppConfiguration.html[@WebAppConfiguration
]
for further details.
@TestConstructor
is a type-level annotation that is used to configure how the parameters
of a test class constructor are autowired from components in the test’s
ApplicationContext
.
If @TestConstructor
is not present or meta-present on a test class, the default test
constructor autowire mode will be used. See the tip below for details on how to change
the default mode. Note, however, that a local declaration of @Autowired
on a
constructor takes precedence over both @TestConstructor
and the default mode.
Tip
|
Changing the default test constructor autowire mode
The default test constructor autowire mode can be changed by setting the
As of Spring Framework 5.3, the default mode may also be configured as a JUnit Platform configuration parameter. If the |
Note
|
As of Spring Framework 5.2, @TestConstructor is only supported in conjunction
with the SpringExtension for use with JUnit Jupiter. Note that the SpringExtension is
often automatically registered for you – for example, when using annotations such as
@SpringJUnitConfig and @SpringJUnitWebConfig or various test-related annotations from
Spring Boot Test.
|
@NestedTestConfiguration
is a type-level annotation that is used to configure how
Spring test configuration annotations are processed within enclosing class hierarchies
for inner test classes.
If @NestedTestConfiguration
is not present or meta-present on a test class, in its
supertype hierarchy, or in its enclosing class hierarchy, the default enclosing
configuration inheritance mode will be used. See the tip below for details on how to
change the default mode.
Tip
|
Changing the default enclosing configuration inheritance mode
The default enclosing configuration inheritance mode is |
The [testcontext-framework] honors @NestedTestConfiguration
semantics for the
following annotations.
Note
|
The use of @NestedTestConfiguration typically only makes sense in conjunction
with @Nested test classes in JUnit Jupiter; however, there may be other testing
frameworks with support for Spring and nested test classes that make use of this
annotation.
|
See [testcontext-junit-jupiter-nested-test-configuration] for an example and further details.
@EnabledIf
is used to signal that the annotated JUnit Jupiter test class or test method
is enabled and should be run if the supplied expression
evaluates to true
.
Specifically, if the expression evaluates to Boolean.TRUE
or a String
equal to true
(ignoring case), the test is enabled. When applied at the class level, all test methods
within that class are automatically enabled by default as well.
Expressions can be any of the following:
-
Spring Expression Language (SpEL) expression. For example:
@EnabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")
-
Placeholder for a property available in the Spring
Environment
. For example:@EnabledIf("${smoke.tests.enabled}")
-
Text literal. For example:
@EnabledIf("true")
Note, however, that a text literal that is not the result of dynamic resolution of a
property placeholder is of zero practical value, since @EnabledIf("false")
is
equivalent to @Disabled
and @EnabledIf("true")
is logically meaningless.
You can use @EnabledIf
as a meta-annotation to create custom composed annotations. For
example, you can create a custom @EnabledOnMac
annotation as follows:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@EnabledIf(
expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
reason = "Enabled on Mac OS"
)
public @interface EnabledOnMac {}
@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@EnabledIf(
expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
reason = "Enabled on Mac OS"
)
annotation class EnabledOnMac {}
Note
|
|
Warning
|
Since JUnit 5.7, JUnit Jupiter also has a condition annotation named |
@DisabledIf
is used to signal that the annotated JUnit Jupiter test class or test
method is disabled and should not be run if the supplied expression
evaluates to
true
. Specifically, if the expression evaluates to Boolean.TRUE
or a String
equal
to true
(ignoring case), the test is disabled. When applied at the class level, all
test methods within that class are automatically disabled as well.
Expressions can be any of the following:
-
Spring Expression Language (SpEL) expression. For example:
@DisabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")
-
Placeholder for a property available in the Spring
Environment
. For example:@DisabledIf("${smoke.tests.disabled}")
-
Text literal. For example:
@DisabledIf("true")
Note, however, that a text literal that is not the result of dynamic resolution of a
property placeholder is of zero practical value, since @DisabledIf("true")
is
equivalent to @Disabled
and @DisabledIf("false")
is logically meaningless.
You can use @DisabledIf
as a meta-annotation to create custom composed annotations. For
example, you can create a custom @DisabledOnMac
annotation as follows:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@DisabledIf(
expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
reason = "Disabled on Mac OS"
)
public @interface DisabledOnMac {}
@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@DisabledIf(
expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
reason = "Disabled on Mac OS"
)
annotation class DisabledOnMac {}
Note
|
|
Warning
|
Since JUnit 5.7, JUnit Jupiter also has a condition annotation named |
You can use most test-related annotations as meta-annotations to create custom composed annotations and reduce configuration duplication across a test suite.
You can use each of the following as a meta-annotation in conjunction with the TestContext framework.
-
@BootstrapWith
-
@ContextConfiguration
-
@ContextHierarchy
-
@ActiveProfiles
-
@TestPropertySource
-
@DirtiesContext
-
@WebAppConfiguration
-
@TestExecutionListeners
-
@Transactional
-
@BeforeTransaction
-
@AfterTransaction
-
@Commit
-
@Rollback
-
@Sql
-
@SqlConfig
-
@SqlMergeMode
-
@SqlGroup
-
@Repeat
(only supported on JUnit 4) -
@Timed
(only supported on JUnit 4) -
@IfProfileValue
(only supported on JUnit 4) -
@ProfileValueSourceConfiguration
(only supported on JUnit 4) -
@SpringJUnitConfig
(only supported on JUnit Jupiter) -
@SpringJUnitWebConfig
(only supported on JUnit Jupiter) -
@TestConstructor
(only supported on JUnit Jupiter) -
@NestedTestConfiguration
(only supported on JUnit Jupiter) -
@EnabledIf
(only supported on JUnit Jupiter) -
@DisabledIf
(only supported on JUnit Jupiter)
Consider the following example:
@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class OrderRepositoryTests { }
@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class UserRepositoryTests { }
@RunWith(SpringRunner::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class OrderRepositoryTests { }
@RunWith(SpringRunner::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class UserRepositoryTests { }
If we discover that we are repeating the preceding configuration across our JUnit 4-based test suite, we can reduce the duplication by introducing a custom composed annotation that centralizes the common test configuration for Spring, as follows:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
annotation class TransactionalDevTestConfig { }
Then we can use our custom @TransactionalDevTestConfig
annotation to simplify the
configuration of individual JUnit 4 based test classes, as follows:
@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class OrderRepositoryTests { }
@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class UserRepositoryTests { }
@RunWith(SpringRunner::class)
@TransactionalDevTestConfig
class OrderRepositoryTests
@RunWith(SpringRunner::class)
@TransactionalDevTestConfig
class UserRepositoryTests
If we write tests that use JUnit Jupiter, we can reduce code duplication even further, since annotations in JUnit 5 can also be used as meta-annotations. Consider the following example:
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
class OrderRepositoryTests { }
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
class UserRepositoryTests { }
@ExtendWith(SpringExtension::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class OrderRepositoryTests { }
@ExtendWith(SpringExtension::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
class UserRepositoryTests { }
If we discover that we are repeating the preceding configuration across our JUnit Jupiter-based test suite, we can reduce the duplication by introducing a custom composed annotation that centralizes the common test configuration for Spring and JUnit Jupiter, as follows:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@ExtendWith(SpringExtension::class)
@ContextConfiguration("/app-config.xml", "/test-data-access-config.xml")
@ActiveProfiles("dev")
@Transactional
annotation class TransactionalDevTestConfig { }
Then we can use our custom @TransactionalDevTestConfig
annotation to simplify the
configuration of individual JUnit Jupiter based test classes, as follows:
@TransactionalDevTestConfig
class OrderRepositoryTests { }
@TransactionalDevTestConfig
class UserRepositoryTests { }
@TransactionalDevTestConfig
class OrderRepositoryTests { }
@TransactionalDevTestConfig
class UserRepositoryTests { }
Since JUnit Jupiter supports the use of @Test
, @RepeatedTest
, ParameterizedTest
,
and others as meta-annotations, you can also create custom composed annotations at the
test method level. For example, if we wish to create a composed annotation that combines
the @Test
and @Tag
annotations from JUnit Jupiter with the @Transactional
annotation from Spring, we could create an @TransactionalIntegrationTest
annotation, as
follows:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Transactional
@Tag("integration-test") // org.junit.jupiter.api.Tag
@Test // org.junit.jupiter.api.Test
public @interface TransactionalIntegrationTest { }
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@Transactional
@Tag("integration-test") // org.junit.jupiter.api.Tag
@Test // org.junit.jupiter.api.Test
annotation class TransactionalIntegrationTest { }
Then we can use our custom @TransactionalIntegrationTest
annotation to simplify the
configuration of individual JUnit Jupiter based test methods, as follows:
@TransactionalIntegrationTest
void saveOrder() { }
@TransactionalIntegrationTest
void deleteOrder() { }
@TransactionalIntegrationTest
fun saveOrder() { }
@TransactionalIntegrationTest
fun deleteOrder() { }
For further details, see the Spring Annotation Programming Model wiki page.