Annotations

This section covers annotations that you can use when you test Spring applications. It includes the following topics:

Spring Testing Annotations

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

@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

@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:

Java
@ContextConfiguration("/test-config.xml") (1)
class XmlApplicationContextTests {
	// class body...
}
1 Referring to an XML file.
Kotlin
@ContextConfiguration("/test-config.xml") (1)
class XmlApplicationContextTests {
	// class body...
}
1 Referring to an XML file.

The following example shows a @ContextConfiguration annotation that refers to a class:

Java
@ContextConfiguration(classes = TestConfig.class) (1)
class ConfigClassApplicationContextTests {
	// class body...
}
1 Referring to a class.
Kotlin
@ContextConfiguration(classes = [TestConfig::class]) (1)
class ConfigClassApplicationContextTests {
	// class body...
}
1 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:

Java
@ContextConfiguration(initializers = CustomContextIntializer.class) (1)
class ContextInitializerTests {
	// class body...
}
Kotlin
@ContextConfiguration(initializers = [CustomContextIntializer::class]) (1)
class ContextInitializerTests {
	// class body...
}
1 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:

Java
@ContextConfiguration(locations = "/test-context.xml", loader = CustomContextLoader.class) (1)
class CustomLoaderXmlApplicationContextTests {
	// class body...
}
1 Configuring both a location and a custom loader.
Kotlin
@ContextConfiguration("/test-context.xml", loader = CustomContextLoader::class) (1)
class CustomLoaderXmlApplicationContextTests {
	// class body...
}
1 Configuring both a location and a custom loader.
@ContextConfiguration provides support for inheriting resource locations or configuration classes as well as context initializers that are declared by superclasses.

See testcontext-ctx-management and the @ContextConfiguration javadocs for further details.

@WebAppConfiguration

@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:

Java
@ContextConfiguration
@WebAppConfiguration (1)
class WebAppTests {
	// class body...
}
Kotlin
@ContextConfiguration
@WebAppConfiguration (1)
class WebAppTests {
	// class body...
}
1 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:

Java
@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources") (1)
class WebAppTests {
	// class body...
}
1 Specifying a classpath resource.
Kotlin
@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources") (1)
class WebAppTests {
	// class body...
}
1 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 @WebAppConfiguration javadoc for further details.

@ContextHierarchy

@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):

Java
@ContextHierarchy({
	@ContextConfiguration("/parent-config.xml"),
	@ContextConfiguration("/child-config.xml")
})
class ContextHierarchyTests {
	// class body...
}
Kotlin
@ContextHierarchy(
	ContextConfiguration("/parent-config.xml"),
	ContextConfiguration("/child-config.xml"))
class ContextHierarchyTests {
	// class body...
}
Java
@WebAppConfiguration
@ContextHierarchy({
	@ContextConfiguration(classes = AppConfig.class),
	@ContextConfiguration(classes = WebConfig.class)
})
class WebIntegrationTests {
	// class body...
}
Kotlin
@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 @ContextHierarchy javadoc for further examples.

@ActiveProfiles

@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:

Java
@ContextConfiguration
@ActiveProfiles("dev") (1)
class DeveloperTests {
	// class body...
}
1 Indicate that the dev profile should be active.
Kotlin
@ContextConfiguration
@ActiveProfiles("dev") (1)
class DeveloperTests {
	// class body...
}
1 Indicate that the dev profile should be active.

The following example indicates that both the dev and the integration profiles should be active:

Java
@ContextConfiguration
@ActiveProfiles({"dev", "integration"}) (1)
class DeveloperIntegrationTests {
	// class body...
}
1 Indicate that the dev and integration profiles should be active.
Kotlin
@ContextConfiguration
@ActiveProfiles(["dev", "integration"]) (1)
class DeveloperIntegrationTests {
	// class body...
}
1 Indicate that the dev and integration profiles should be active.
@ActiveProfiles provides support for inheriting active bean definition profiles declared by superclasses 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 and the @ActiveProfiles javadoc for examples and further details.

@TestPropertySource

@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.

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 through @PropertySource or programmatically. Thus, test property sources can be used to selectively override properties defined in system and application property sources. Furthermore, inlined properties have higher precedence than properties loaded from resource locations.

The following example demonstrates how to declare a properties file from the classpath:

Java
@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
	// class body...
}
1 Get properties from test.properties in the root of the classpath.
Kotlin
@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
	// class body...
}
1 Get properties from test.properties in the root of the classpath.

The following example demonstrates how to declare inlined properties:

Java
@ContextConfiguration
@TestPropertySource(properties = { "timezone = GMT", "port: 4242" }) (1)
class MyIntegrationTests {
	// class body...
}
1 Declare timezone and port properties.
Kotlin
@ContextConfiguration
@TestPropertySource(properties = ["timezone = GMT", "port: 4242"]) (1)
class MyIntegrationTests {
	// class body...
}
1 Declare timezone and port properties.

See testcontext-ctx-management-property-sources for examples and further details.

@DirtiesContext

@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
    }
    1 Dirty the context before the current test class.
    Kotlin
    @DirtiesContext(classMode = BEFORE_CLASS) (1)
    class FreshContextTests {
    	// some tests that require a new Spring container
    }
    1 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
    }
    1 Dirty the context after the current test class.
    Kotlin
    @DirtiesContext (1)
    class ContextDirtyingTests {
    	// some tests that result in the Spring container being dirtied
    }
    1 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
    }
    1 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
    }
    1 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
    }
    1 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
    }
    1 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
    }
    1 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
    }
    1 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
    }
    1 Dirty the context after the current test method.
    Kotlin
    @DirtiesContext (1)
    @Test
    fun testProcessWhichDirtiesAppCtx() {
    	// some logic that results in the Spring container being dirtied
    }
    1 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.

Java
@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
	}
}
1 Use the current-level algorithm.
Kotlin
@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
	}
}
1 Use the current-level algorithm.

For further details regarding the EXHAUSTIVE and CURRENT_LEVEL algorithms, see the DirtiesContext.HierarchyMode javadoc.

@TestExecutionListeners

@TestExecutionListeners defines class-level metadata for configuring the TestExecutionListener implementations that should be registered with the TestContextManager. Typically, @TestExecutionListeners is used in conjunction with @ContextConfiguration.

The following example shows how to register two TestExecutionListener implementations:

Java
@ContextConfiguration
@TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class}) (1)
class CustomTestExecutionListenerTests {
	// class body...
}
1 Register two TestExecutionListener implementations.
Kotlin
@ContextConfiguration
@TestExecutionListeners(CustomTestExecutionListener::class, AnotherTestExecutionListener::class) (1)
class CustomTestExecutionListenerTests {
	// class body...
}
1 Register two TestExecutionListener implementations.

By default, @TestExecutionListeners supports inherited listeners. See the javadoc for an example and further details.

@Commit

@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:

Java
@Commit (1)
@Test
void testProcessWithoutRollback() {
	// ...
}
1 Commit the result of the test to the database.
Kotlin
@Commit (1)
@Test
fun testProcessWithoutRollback() {
	// ...
}
1 Commit the result of the test to the database.
@Rollback

@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 spring-testing-annotation-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):

Java
@Rollback(false) (1)
@Test
void testProcessWithoutRollback() {
	// ...
}
1 Do not roll back the result.
Kotlin
@Rollback(false) (1)
@Test
fun testProcessWithoutRollback() {
	// ...
}
1 Do not roll back the result.
@BeforeTransaction

@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:

Java
@BeforeTransaction (1)
void beforeTransaction() {
	// logic to be executed before a transaction is started
}
1 Run this method before a transaction.
Kotlin
@BeforeTransaction (1)
fun beforeTransaction() {
	// logic to be executed before a transaction is started
}
1 Run this method before a transaction.
@AfterTransaction

@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.

Java
@AfterTransaction (1)
void afterTransaction() {
	// logic to be executed after a transaction has ended
}
1 Run this method after a transaction.
Kotlin
@AfterTransaction (1)
fun afterTransaction() {
	// logic to be executed after a transaction has ended
}
1 Run this method after a transaction.
@Sql

@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:

Java
@Test
@Sql({"/test-schema.sql", "/test-user-data.sql"}) (1)
void userTest() {
	// execute code that relies on the test schema and test data
}
1 Run two scripts for this test.
Kotlin
@Test
@Sql("/test-schema.sql", "/test-user-data.sql") (1)
fun userTest() {
	// execute code that relies on the test schema and test data
}
1 Run two scripts for this test.

See testcontext-executing-sql-declaratively for further details.

@SqlConfig

@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:

Java
@Test
@Sql(
	scripts = "/test-user-data.sql",
	config = @SqlConfig(commentPrefix = "`", separator = "@@") (1)
)
void userTest() {
	// execute code that relies on the test data
}
1 Set the comment prefix and the separator in SQL scripts.
Kotlin
@Test
@Sql("/test-user-data.sql", config = SqlConfig(commentPrefix = "`", separator = "@@")) (1)
fun userTest() {
	// execute code that relies on the test data
}
1 Set the comment prefix and the separator in SQL scripts.
@SqlMergeMode

@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.

Java
@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
@SqlMergeMode(MERGE) (1)
class UserTests {

	@Test
	@Sql("/user-test-data-001.sql")
	void standardUserProfile() {
		// execute code that relies on test data set 001
	}
}
1 Set the @Sql merge mode to MERGE for all test methods in the class.
Kotlin
@SpringJUnitConfig(TestConfig::class)
@Sql("/test-schema.sql")
@SqlMergeMode(MERGE) (1)
class UserTests {

	@Test
	@Sql("/user-test-data-001.sql")
	fun standardUserProfile() {
		// execute code that relies on test data set 001
	}
}
1 Set the @Sql merge mode to MERGE for all test methods in the class.

The following example shows how to use @SqlMergeMode at the method level.

Java
@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
class UserTests {

	@Test
	@Sql("/user-test-data-001.sql")
	@SqlMergeMode(MERGE) (1)
	void standardUserProfile() {
		// execute code that relies on test data set 001
	}
}
1 Set the @Sql merge mode to MERGE for a specific test method.
Kotlin
@SpringJUnitConfig(TestConfig::class)
@Sql("/test-schema.sql")
class UserTests {

	@Test
	@Sql("/user-test-data-001.sql")
	@SqlMergeMode(MERGE) (1)
	fun standardUserProfile() {
		// execute code that relies on test data set 001
	}
}
1 Set the @Sql merge mode to MERGE for a specific test method.
@SqlGroup

@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:

Java
@Test
@SqlGroup({ (1)
	@Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")),
	@Sql("/test-user-data.sql")
)}
void userTest() {
	// execute code that uses the test schema and test data
}
1 Declare a group of SQL scripts.
Kotlin
@Test
@SqlGroup( (1)
	Sql("/test-schema.sql", config = SqlConfig(commentPrefix = "`")),
	Sql("/test-user-data.sql"))
fun userTest() {
	// execute code that uses the test schema and test data
}
1 Declare a group of SQL scripts.

Standard Annotation Support

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 (javax.annotation) if JSR-250 is present

  • @ManagedBean (javax.annotation) if JSR-250 is present

  • @Inject (javax.inject) if JSR-330 is present

  • @Named (javax.inject) if JSR-330 is present

  • @PersistenceContext (javax.persistence) if JPA is present

  • @PersistenceUnit (javax.persistence) if JPA is present

  • @Required

  • @Transactional (org.springframework.transaction.annotation) with limited attribute support

JSR-250 Lifecycle Annotations

In the Spring TestContext Framework, you can use @PostConstruct and @PreDestroy with standard semantics on any application components configured in the ApplicationContext. However, these lifecycle annotations have limited usage within an actual test class.

If a method within a test class is annotated with @PostConstruct, that method runs before any before methods of the underlying test framework (for example, methods annotated with JUnit Jupiter’s @BeforeEach), and that applies for every test method in the test class. On the other hand, if a method within a test class is annotated with @PreDestroy, that method never runs. Therefore, within a test class, we recommend that you use test lifecycle callbacks from the underlying test framework instead of @PostConstruct and @PreDestroy.

Spring JUnit 4 Testing Annotations

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

@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:

Java
@IfProfileValue(name="java.vendor", value="Oracle Corporation") (1)
@Test
public void testProcessWhichRunsOnlyOnOracleJvm() {
	// some logic that should run only on Java VMs from Oracle Corporation
}
1 Run this test only when the Java vendor is "Oracle Corporation".
Kotlin
@IfProfileValue(name="java.vendor", value="Oracle Corporation") (1)
@Test
fun testProcessWhichRunsOnlyOnOracleJvm() {
	// some logic that should run only on Java VMs from Oracle Corporation
}
1 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:

Java
@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
}
1 Run this test for unit tests and integration tests.
Kotlin
@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
}
1 Run this test for unit tests and integration tests.
@ProfileValueSourceConfiguration

@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:

Java
@ProfileValueSourceConfiguration(CustomProfileValueSource.class) (1)
public class CustomProfileValueSourceTests {
	// class body...
}
1 Use a custom profile value source.
Kotlin
@ProfileValueSourceConfiguration(CustomProfileValueSource::class) (1)
class CustomProfileValueSourceTests {
	// class body...
}
1 Use a custom profile value source.
@Timed

@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:

Java
@Timed(millis = 1000) (1)
public void testProcessWithOneSecondTimeout() {
	// some logic that should not take longer than 1 second to execute
}
1 Set the time period for the test to one second.
Kotlin
@Timed(millis = 1000) (1)
fun testProcessWithOneSecondTimeout() {
	// some logic that should not take longer than 1 second to execute
}
1 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

@Repeat indicates that the annotated test method must be run repeatedly. The number of times that the test method is to be executed 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. The following example shows how to use the @Repeat annotation:

Java
@Repeat(10) (1)
@Test
public void testProcessRepeatedly() {
	// ...
}
1 Repeat this test ten times.
Kotlin
@Repeat(10) (1)
@Test
fun testProcessRepeatedly() {
	// ...
}
1 Repeat this test ten times.

Spring JUnit Jupiter Testing Annotations

The following annotations are supported only when used in conjunction with the SpringExtension and JUnit Jupiter (that is, the programming model in JUnit 5):

@SpringJUnitConfig

@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:

Java
@SpringJUnitConfig(TestConfig.class) (1)
class ConfigurationClassJUnitJupiterSpringTests {
	// class body...
}
1 Specify the configuration class.
Kotlin
@SpringJUnitConfig(TestConfig::class) (1)
class ConfigurationClassJUnitJupiterSpringTests {
	// class body...
}
1 Specify the configuration class.

The following example shows how to use the @SpringJUnitConfig annotation to specify the location of a configuration file:

Java
@SpringJUnitConfig(locations = "/test-config.xml") (1)
class XmlJUnitJupiterSpringTests {
	// class body...
}
1 Specify the location of a configuration file.
Kotlin
@SpringJUnitConfig(locations = ["/test-config.xml"]) (1)
class XmlJUnitJupiterSpringTests {
	// class body...
}
1 Specify the location of a configuration file.

See testcontext-ctx-management as well as the javadoc for @SpringJUnitConfig and @ContextConfiguration for further details.

@SpringJUnitWebConfig

@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:

Java
@SpringJUnitWebConfig(TestConfig.class) (1)
class ConfigurationClassJUnitJupiterSpringWebTests {
	// class body...
}
1 Specify the configuration class.
Kotlin
@SpringJUnitWebConfig(TestConfig::class) (1)
class ConfigurationClassJUnitJupiterSpringWebTests {
	// class body...
}
1 Specify the configuration class.

The following example shows how to use the @SpringJUnitWebConfig annotation to specify a the location of a configuration file:

Java
@SpringJUnitWebConfig(locations = "/test-config.xml") (1)
class XmlJUnitJupiterSpringWebTests {
	// class body...
}
1 Specify the location of a configuration file.
Kotlin
@SpringJUnitWebConfig(locations = ["/test-config.xml"]) (1)
class XmlJUnitJupiterSpringWebTests {
	// class body...
}
1 Specify the location of a configuration file.

See testcontext-ctx-management as well as the javadoc for @SpringJUnitWebConfig, @ContextConfiguration, and @WebAppConfiguration for further details.

@TestConstructor

@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.

Changing the default test constructor autowire mode

The default test constructor autowire mode can be changed by setting the spring.test.constructor.autowire.mode JVM system property to all. Alternatively, the default mode may be changed via the SpringProperties mechanism.

If the spring.test.constructor.autowire.mode property is not set, test class constructors will not be automatically autowired.

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.
@EnabledIf

@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:

Java
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@EnabledIf(
	expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
	reason = "Enabled on Mac OS"
)
public @interface EnabledOnMac {}
Kotlin
@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@EnabledIf(
		expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
		reason = "Enabled on Mac OS"
)
annotation class EnabledOnMac {}
@DisabledIf

@DisabledIf is used to signal that the annotated JUnit Jupiter test class or test method is disabled and should not be executed 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:

Java
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@DisabledIf(
	expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
	reason = "Disabled on Mac OS"
)
public @interface DisabledOnMac {}
Kotlin
@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@DisabledIf(
		expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
		reason = "Disabled on Mac OS"
)
annotation class DisabledOnMac {}

Meta-Annotation Support for Testing

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)

  • @EnabledIf (only supported on JUnit Jupiter)

  • @DisabledIf (only supported on JUnit Jupiter)

Consider the following example:

Java
@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 { }
Kotlin
@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:

Java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }
Kotlin
@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:

Java
@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class OrderRepositoryTests { }

@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class UserRepositoryTests { }
Kotlin
@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:

Java
@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 { }
Kotlin
@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:

Java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }
Kotlin
@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:

Java
@TransactionalDevTestConfig
class OrderRepositoryTests { }

@TransactionalDevTestConfig
class UserRepositoryTests { }
Kotlin
@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:

Java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Transactional
@Tag("integration-test") // org.junit.jupiter.api.Tag
@Test // org.junit.jupiter.api.Test
public @interface TransactionalIntegrationTest { }
Kotlin
@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:

Java
@TransactionalIntegrationTest
void saveOrder() { }

@TransactionalIntegrationTest
void deleteOrder() { }
Kotlin
@TransactionalIntegrationTest
fun saveOrder() { }

@TransactionalIntegrationTest
fun deleteOrder() { }

For further details, see the Spring Annotation Programming Model wiki page.