Spring Framework contains the following set of Spring-specific annotations that can be used in your unit and integration tests in conjunction with the TestContext framework. See the corresponding javadoc for more information, including default attribute values, attribute aliases, and more.
The following annotations exist for testing in Spring:
@BootstrapWith
@BootstrapWith
is a class-level annotation that can be used to configure how the Spring
TestContext Framework bootstraps. In particular, you can use @BootstrapWith
to specify a special TestContextBootstrapper
.
For more information, see Bootstrapping
the TestContext framework.
@ContextConfiguration
The @ContextConfiguration
annotation defines class-level metadata that is used to determine how
to load and configure the ApplicationContext
for integration tests. Specifically,
@ContextConfiguration declares the locations
of application context resources or 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 usually classes with the @Configuration
annotation. However, resource
locations can also reference files and scripts on the file system, and component classes can be classes
annotated with @Component
, @Service
, and so on. For more information, see "Component
Classes".
The following example shows the @ContextConfiguration
annotation that references an XML file:
@ContextConfiguration("/test-config.xml")
class XmlApplicationContextTests {
// class body...
}
- Referring to the XML file.
@ContextConfiguration("/test-config.xml")
class XmlApplicationContextTests {
// class body...
}
- Referring to the XML file.
The following example shows @ContextConfiguration
annotation that references the class:
@ContextConfiguration(classes = TestConfig.class)
class ConfigClassApplicationContextTests {
// class body...
}
- Reference to the class.
@ContextConfiguration(classes = [TestConfig::class])
class ConfigClassApplicationContextTests {
// class body...
}
- Referencing a class.
Alternatively, or in addition to declaring a lookup for resource locations or component classes, you can
use @ContextConfiguration
to declare the ApplicationContextInitializer
classes. The
following example shows such a case:
@ContextConfiguration(initializers = CustomContextInitializer.class)
class ContextInitializerTests {
// class body...
}
- Declare the class -initializer.
@ContextConfiguration(initializers = [CustomContextInitializer::class])
class ContextInitializerTests {
// class body...
}
- Declare an initializer class.
You can also use the @ContextConfiguration
annotation to declare the ContextLoader
strategy. Note, however, that it is often not necessary to explicitly configure the loader, since the default
loader supports initializers
and either locations
resources or component
classes
.
The following example uses both the location and the loader:
@ContextConfiguration(locations = "/test-context.xml", loader = CustomContextLoader.class)
class CustomLoaderXmlApplicationContextTests {
// class body...
}
- Configure both the location and the custom bootloader.
@ContextConfiguration("/test-context.xml", loader = CustomContextLoader::class)
class CustomLoaderXmlApplicationContextTests {
// class body..
}
- Configure both the location and the custom bootloader.
@ContextConfiguration
provides support for inheriting
resource locations or configuration classes, as well as context initializers that are declared by superclasses
or enclosing classes.
See section dedicated to context
management, test
class configurations with the annotation @Nested
and javadocs with the annotation @ContextConfiguration
for more details.
@WebAppConfiguration
@WebAppConfiguration
is a class-level annotation that can be used to declare that the ApplicationContext
for an integration test should be WebApplicationContext
. The very presence
of the @WebAppConfiguration
annotation in the test class ensures that the test will load the WebApplicationContext
using the default value "file:src/main/webapp"
for the path to the web application root (that is,
the main resource path). The main resource path is used behind the scenes to create a
MockServletContext
that serves as the ServletContext for the WebApplicationContext
test.
The following example shows how to use the annotation @WebAppConfiguration
:
@ContextConfiguration
@WebAppConfiguration
class WebAppTests {
// class body...
}
- Annotation
@WebAppConfiguration
.
@ContextConfiguration
@WebAppConfiguration
class WebAppTests {
// class body...
}
- Annotation
@WebAppConfiguration
.
To override the default value, you can set a different primary resource path using an explicit value
attribute. Resource prefixes classpath:
and file:
are supported. If a resource prefix
is not specified, the path is assumed to be a file system resource. The following example shows how to set a
classpath resource:
@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources")
class WebAppTests {
// class body...
}
- Set a classpath resource.
@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources")
class WebAppTests {
// class body...
}
- Set a classpath resource.
Note that the @WebAppConfiguration
annotation must be used either in combination with the @ContextConfiguration
within one test class, or within a hierarchy of test classes. For
more information, see the javadoc annotation @WebAppConfiguration
.
@ContextHierarchy
@ContextHierarchy
is a class-level annotation that is used to define a hierarchy of ApplicationContext
instances for integration tests. The @ContextHierarchy
annotation must be declared using a list of
one or more instances of the @ContextConfiguration
annotation, each of which defines a level in the
context hierarchy. The following examples show the use of the @ContextHierarchy
annotation within a
single test class (the @ContextHierarchy
annotation 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 want to merge or override the configuration for a given level of the context hierarchy in the test class
hierarchy, you must explicitly give this level a name by passing the same value to the name
attribute in the @ContextConfiguration
annotation for each corresponding level of the class
hierarchy. For more examples, see "Context
Hierarchies" and javadoc by annotation @ContextHierarchy
.
@ActiveProfiles
@ActiveProfiles
is a class-level annotation that is used to declare which bean definition profiles
must be active when loading ApplicationContext
for an integration test.
The following example shows that the dev
profile must be active:
@ContextConfiguration
@ActiveProfiles("dev")
class DeveloperTests {
// class body. ..
}
- Indicate that the
dev
profile should be active.
@ContextConfiguration
@ActiveProfiles("dev")
class DeveloperTests {
// class body...
}
- Indicate that the profile is
dev
must be active.
The following example shows that both the dev
and integration
profiles must be active:
@ContextConfiguration
@ActiveProfiles({"dev", "integration"})
class DeveloperIntegrationTests {
// class body...
}
- We indicate that the
dev
andintegration
profiles should be active.
@ContextConfiguration
@ActiveProfiles(["dev", "integration"])
class DeveloperIntegrationTests {
// class body...
}
- Indicate that the
dev
andintegration
profiles should be active.
@ActiveProfiles
annotation provides support for
inheriting active bean definition profiles declared by superclasses and default enclosing classes. You can also
programmatically resolve active bean definition profiles by implementing a custom ActiveProfilesResolver
and registering it using the resolver
attribute of the @ActiveProfiles
annotation.
See: sections "Context
configuration using environment profiles", "Configuration
of a test class with the annotation @Nested"
, as well as javadoc annotation @ActiveProfiles
for examples and more detailed information.
@TestPropertySource
@TestPropertySource
– is a class-level annotation that can be used to configure the locations of
property files and inline properties to be added to the PropertySources
bundle in the
Environment
for the ApplicationContext,
loaded for an integration test.
The following example shows how to declare a properties file from the classpath:
@ContextConfiguration
@TestPropertySource("/test.properties")
class MyIntegrationTests {
// class body...
}
- Get properties from
test.properties
in the root classpath.
@ContextConfiguration
@TestPropertySource("/test.properties")
class MyIntegrationTests {
// class body..
}
- Get properties from
test.properties
at the root of the classpath.
The following example shows how to declare inline properties:
@ContextConfiguration
@TestPropertySource(properties = { "timezone = GMT", "port: 4242" })
class MyIntegrationTests {
// class body...
}
- Declare the properties
timezone
andport
.
@ContextConfiguration
@TestPropertySource(properties = ["timezone = GMT", "port: 4242"])
class MyIntegrationTests {
// class body...
}
- Declare the
timezone
andport
properties.
For examples and more information, see "Context configuration using test property sources".
@DynamicPropertySource
@DynamicPropertySource
is a method-level annotation that can be used to register dynamic
properties added to the PropertySources
bundle in Environment
for
ApplicationContext
loaded for the integration test. Dynamic properties are useful if the property
values are not known in advance - for example, if the properties are managed by an external resource, as is the case
with a container managed by the project Testcontainers.
The following example shows how to register a dynamic property:
@ContextConfiguration
class MyIntegrationTests {
static MyExternalServer server = // ...
@DynamicPropertySource
static void dynamicProperties(DynamicPropertyRegistry registry) {
registry.add("server.port", server::getPort);
}
// tests ...
}
- Mark the
static
method with the annotation@DynamicPropertySource
. - Accept
DynamicPropertyRegistry
as an argument . - Register the dynamic property
server.port
, which will be received from the server later.
@ContextConfiguration
class MyIntegrationTests {
companion object {
@JvmStatic
val server: MyExternalServer = // ...
@DynamicPropertySource
@JvmStatic
fun dynamicProperties(registry: DynamicPropertyRegistry) {
registry.add("server.port", server::getPort)
}
}
// tests ...
}
- Mark the
static
method with the annotation@DynamicPropertySource
. - We accept
DynamicPropertyRegistry
as an argument. - We register the dynamic property
server.port
, which will be received from the server deferred.< /li>
For more information, see "Context configuration using dynamic property sources".
@DirtiesContext
The @DirtiesContext
annotation indicates that the underlying ApplicationContext
is from
Spring was "contaminated" during test execution (that is, the test changed or corrupted it in some way - for
example, changing the state of a singleton bean) and needs to be closed. If an application context is marked as
dirty, it is removed from the testing system cache and closed. As a result, the base Spring container is rebuilt for
any subsequent test that necessarily requires a context with the same configuration metadata.
The @DirtiesContext
annotation can be used both at the class level and at the method level within a single class or class hierarchy. In
such scenarios, the ApplicationContext
is marked as dirty before or after any such annotated method,
and before or after the current test class, depending on the configured methodMode
and
classMode
.
The following examples explain when the context can be "polluted" under various configuration scenarios:
Before the current test class, if declared for a class using the class mode set to
BEFORE_CLASS
.Java@DirtiesContext(classMode = BEFORE_CLASS) class FreshContextTests { // some tests that require a new Spring container }
- "Dirty" context before the current test class.
Kotlin@DirtiesContext(classMode = BEFORE_CLASS ) class FreshContextTests { // some tests that require a new Spring container }
- The "dirty" context is before the current test class.
After the current test class, if declared for a class whose class mode is set to
AFTER_CLASS
(i.e. default class mode).Java@DirtiesContext class ContextDirtyingTests { // some tests that pollute the Spring container }
- "Dirty" context after the current one test class.
Kotlin@DirtiesContext class ContextDirtyingTests { // some tests that cause the Spring container to become dirty }
- "Dirty" context after the current test class.
Before each test method in the current test class, if declared for a class whose class mode is set to
BEFORE_EACH_TEST_METHOD
.Java@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD) class FreshContextTests { // some tests that require a new Spring container }
- Dirty context before each test method.
Kotlin@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD) class FreshContextTests { // some tests that require a new Spring container }
- " Dirty" context before each test method.
After each test method in the current test class, if declared for a class whose class mode is set to
AFTER_EACH_TEST_METHOD
.Java@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) class ContextDirtyingTests { // some tests that cause the Spring container to become dirty }
- "Dirty" context after each test method.
Kotlin@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) class ContextDirtyingTests { // some tests that lead to Spring container contamination }
- Dirty context after each test method.
Before the current test, if declared for a method whose method mode is set to
BEFORE_METHOD
.Java@DirtiesContext(methodMode = BEFORE_METHOD) @Test void testProcessWhichRequiresFreshAppCtx() { // some logic that requires a new Spring container }
- "Dirty" context before the current test method.
Kotlin@DirtiesContext(methodMode = BEFORE_METHOD) @Test fun testProcessWhichRequiresFreshAppCtx() { // some logic that requires a new Spring container }
- "Dirty" context before the current test method.
After the current test, if declared in a method whose method mode is set to
AFTER_METHOD
(i.e. default method mode).Java@DirtiesContext @Test void testProcessWhichDirtiesAppCtx() { // some logic that causes the Spring container to become dirty }
- "Dirty " context after the current test method.
Kotlin@DirtiesContext @Test fun testProcessWhichDirtiesAppCtx() { // some logic that pollutes the Spring container }
- The "dirty" context after the current test method.
If you use the @DirtiesContext
annotation in a test whose context is configured as part of a
context hierarchy using the @ContextHierarchy
annotation, the hierarchyMode
flag can be
used to control the process of clearing the context cache. By default, to clear the context cache, an exhaustive
search algorithm is used, affecting not only the current level, but also all other context hierarchies that have a
common ancestor context with the current test. All instances of ApplicationContext
that are in the
common ancestor context hierarchy branch are removed from the context cache and closed. If the exhaustive search
algorithm is overkill for a particular use case, then you can specify a simpler current-level algorithm, as shown in
the following example.
@ContextHierarchy({
@ContextConfiguration("/parent-config.xml"),
@ContextConfiguration("/child-config.xml")
})
class BaseTests {
// class body...
}
class ExtendedTests extends BaseTests {
@Test
@DirtiesContext(hierarchyMode = CURRENT_LEVEL)
void test() {
// some logic that pollutes the child context
}
}
- We 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)
fun test() {
// some logic that pollutes the child context
}
}
- We use the current level algorithm.
More information about the algorithms EXHAUSTIVE
and CURRENT_LEVEL
see javadoc at "DirtiesContext.HierarchyMode"
.
@TestExecutionListeners
@TestExecutionListeners
is used to register listeners for a specific test class, its subclasses and
nested classes. If you need to register a listener globally, you should register it through the automatic
discovery mechanism described in the Configuration
section TestExecutionListener
.
The following example shows how to register two implementations of TestExecutionListener
:
@ContextConfiguration
@TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class})
class CustomTestExecutionListenerTests {
// class body...
}
- Register two implementations of
TestExecutionListener
.
@ContextConfiguration
@TestExecutionListeners(CustomTestExecutionListener::class, AnotherTestExecutionListener::class)
class CustomTestExecutionListenerTests {
// class body...
}
- Register two implementations
TestExecutionListener
.
By default, the @TestExecutionListeners
annotation provides support for inheriting listeners from
superclasses or enclosing classes. See "Test
class configuration with @Nested annotation"
and javadoc by annotation @TestExecutionListeners
for an example and detailed information. If
you find that you need to revert to using standard TestExecutionListener
implementations, please
see the note in "Registering
implementations of TestExecutionListener"
.
@RecordApplicationEvents
Annotation @RecordApplicationEvents
is an annotation on class level, which is used to instruct the
Spring TestContext Framework to record all application events that are published to the ApplicationContext
during the execution of a single test.
Recorded events can be accessed through the ApplicationEvents
API within tests.
See: javadoc on "Application
Events" and "@RecordApplicationEvents Annotations"
for an example and obtain further
details.
@Commit
The @Commit
annotation specifies that the transaction for a transactional test method should be
committed after the test method completes. You can use the @Commit
annotation as a direct
replacement for the @Rollback(false)
annotation to make the code more explicit. Similar to the
@Rollback
annotation, the @Commit
annotation can also be declared as a class- or
method-level annotation.
The following example shows how to use the annotation @Commit
:
@Commit
@Test
void testProcessWithoutRollback() {
// ...
}
- Fix the test result in the database .
@Commit
@Test
fun testProcessWithoutRollback() {
// ...
}
- Fix the test result in the database.
@Rollback
The @Rollback
annotation specifies whether the transaction for a transactional
test method should be rolled back after the test method completes. If set to 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 the
@Rollback
annotation is not explicitly declared.
If the annotation is @Rollback
is
declared as a class-level annotation, then it defines the default rollback semantics for all test methods in the
test class hierarchy. If the @Rollback
annotation is declared at the method level, it defines the
rollback semantics for a particular test method, potentially overriding the semantics of the @Rollback
or @Commit
annotation at the level class.
In the following example, the result of the test method is not rolled back (that is, the result is committed to the database):
@Rollback(false )
@Test
void testProcessWithoutRollback() {
// ...
}
- We do not roll back the result.
@Rollback(false)
@Test
fun testProcessWithoutRollback() {
// ...
}
- We do not roll back the result.
@BeforeTransaction
The @BeforeTransaction
annotation indicates that the annotated void
the method
should be executed before the transaction begins in the case of test methods configured to execute within a
transaction via the @Transactional
annotation from Spring. Methods marked with the @BeforeTransaction
annotation are optional must be public
, and they can be declared in interface methods with the default
implementation based on Java 8.
The following example shows how to use the annotation @BeforeTransaction
:
@BeforeTransaction
void beforeTransaction() {
// logic that should be executed before the transaction begins
}
- Run this method before the transaction.
@BeforeTransaction
fun beforeTransaction() {
// logic that should be executed before the transaction begins
}
- Run this method before the transaction.
@AfterTransaction
The @AfterTransaction
annotation specifies that the void
annotated method should be
executed after the transaction completes in the case of test methods configured to execute within a transaction via
the @Transactional
annotation from Spring. Methods marked with the @AfterTransaction
annotation do not need to be public
, and they can be declared in interface methods with the default
Java 8-based implementation.
@AfterTransaction
void afterTransaction() {
// logic that will be executed after the transaction is completed
}
- We execute this method after the transaction.
AfterTransaction
fun afterTransaction() {
// logic that will be executed after the transaction is completed
}
- We execute this method after the transaction.
@Sql
The @Sql
annotation is used to annotate a test class or test method to configure the SQL scripts
that will be executed against a given database during integration tests. The following example shows how to use
it:
@Test
@Sql({"/test-schema.sql", "/test-user-data.sql"})
void userTest() {
// execute code that uses test circuit and test data
}
- Run two scripts for this test.
@Test
@Sql("/test-schema.sql", "/test-user-data.sql")
fun userTest() {
// execute code that uses test circuit and test data
}
- Run two scripts for this test.
For more information, see "Declaratively executing SQL scripts using @Sql annotations.
@SqlConfig
The @SqlConfig
annotation 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 = "@@")
)
void userTest() {
// execute code that uses test data
}
- Set the comment prefix and delimiter in SQL scripts.
@Test
@Sql("/test-user-data.sql", config = SqlConfig(commentPrefix = "`", separator = "@@"))
fun userTest() {
// execute code that uses test data
}
- Set the comment prefix and delimiter in SQL scripts.
@SqlMergeMode
The @SqlMergeMode
annotation is used to annotate a test class or test method to configure
the method level @Sql
annotation declarations to be merged with the
@Sql
annotation declarations at the class level. If the @SqlMergeMode
annotation has not been declared for a test class or test method, then the default merge mode OVERRIDE
will be used. In OVERRIDE
mode, @Sql
annotation declarations at the method
level will effectively override @Sql
annotation declarations at the class level.
Note that declaring the @SqlMergeMode
annotation at the method level overrides the
declaration at the class level.
The following example shows how to use the annotation @SqlMergeMode
at the class level.
@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
@SqlMergeMode(MERGE)
class UserTests {
@Test
@Sql("/user-test-data-001.sql")
void standardUserProfile() {
// execute code that uses test data set 001
}
}
- Set the
@Sql
annotation merging mode toMERGE
for all test methods in the class.
@SpringJUnitConfig(TestConfig::class)
@Sql("/test-schema.sql")
@SqlMergeMode(MERGE)
class UserTests {
@Test
@Sql("/user-test-data-001.sql")
fun standardUserProfile() {
// execute code that uses test data set 001
}
}
- Set the
@Sql
annotation merging mode toMERGE
for all test methods in the class.
The following example shows how to use the annotation @SqlMergeMode
at the method level.
@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
class UserTests {
@Test
@Sql("/user-test-data-001.sql")
@SqlMergeMode(MERGE)
void standardUserProfile() {
// execute code that uses test data set 001
}
}
- Set the
@Sql
annotation merging 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)
fun standardUserProfile() {
// execute code that uses test data set 001
}
}
- Set the
@Sql
annotation merging mode toMERGE
for a specific test method.
@SqlGroup
@SqlGroup
is a container annotation that combines multiple @Sql
annotations. You can use the @SqlGroup
annotation to declare multiple nested
@Sql
annotations, or use it in combination with the Java 8 duplicate annotation support
where the @Sql
annotation can be declared multiple times for the same class or method,
implicitly generating this container annotation. The following example shows how to declare an SQL
group:
@Test
@SqlGroup({
@Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")),
@Sql("/test-user-data.sql")
})
void userTest() {
// execute code using test circuit and test data
}
- Declare a group of SQL scripts.
@Test
@SqlGroup(
Sql("/test-schema.sql", config = SqlConfig(commentPrefix = "`")),
Sql("/test-user-data.sql"))
fun userTest() {
// execute code using test circuit and test data
}
- Declare a group of SQL scripts.