Split files
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
[[integration-testing-annotations-junit-jupiter]]
|
||||
= Spring JUnit Jupiter Testing Annotations
|
||||
|
||||
The following annotations are supported when used in conjunction with the
|
||||
<<testcontext-junit-jupiter-extension, `SpringExtension`>> and JUnit Jupiter
|
||||
(that is, the programming model in JUnit 5):
|
||||
|
||||
* <<integration-testing-annotations-junit-jupiter-springjunitconfig>>
|
||||
* <<integration-testing-annotations-junit-jupiter-springjunitwebconfig>>
|
||||
* <<integration-testing-annotations-testconstructor>>
|
||||
* <<integration-testing-annotations-nestedtestconfiguration>>
|
||||
* <<integration-testing-annotations-junit-jupiter-enabledif>>
|
||||
* <<integration-testing-annotations-junit-jupiter-disabledif>>
|
||||
|
||||
[[integration-testing-annotations-junit-jupiter-springjunitconfig]]
|
||||
== `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@SpringJUnitConfig(TestConfig.class) // <1>
|
||||
class ConfigurationClassJUnitJupiterSpringTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Specify the configuration class.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@SpringJUnitConfig(locations = "/test-config.xml") // <1>
|
||||
class XmlJUnitJupiterSpringTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Specify the location of a configuration file.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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
|
||||
{api-spring-framework}/test/context/junit/jupiter/SpringJUnitConfig.html[`@SpringJUnitConfig`]
|
||||
and `@ContextConfiguration` for further details.
|
||||
|
||||
[[integration-testing-annotations-junit-jupiter-springjunitwebconfig]]
|
||||
== `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@SpringJUnitWebConfig(TestConfig.class) // <1>
|
||||
class ConfigurationClassJUnitJupiterSpringWebTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Specify the configuration class.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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 the
|
||||
location of a configuration file:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@SpringJUnitWebConfig(locations = "/test-config.xml") // <1>
|
||||
class XmlJUnitJupiterSpringWebTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Specify the location of a configuration file.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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
|
||||
{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.
|
||||
|
||||
[[integration-testing-annotations-testconstructor]]
|
||||
== `@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
|
||||
[TIP]
|
||||
=====
|
||||
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 set via the
|
||||
<<appendix.adoc#appendix-spring-properties,`SpringProperties`>> mechanism.
|
||||
|
||||
As of Spring Framework 5.3, the default mode may also be configured as a
|
||||
https://junit.org/junit5/docs/current/user-guide/#running-tests-config-params[JUnit Platform configuration parameter].
|
||||
|
||||
If the `spring.test.constructor.autowire.mode` property is not set, test class
|
||||
constructors will not be automatically autowired.
|
||||
=====
|
||||
|
||||
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.
|
||||
|
||||
[[integration-testing-annotations-nestedtestconfiguration]]
|
||||
== `@NestedTestConfiguration`
|
||||
|
||||
`@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.
|
||||
|
||||
.Changing the default enclosing configuration inheritance mode
|
||||
[TIP]
|
||||
=====
|
||||
The default _enclosing configuration inheritance mode_ is `INHERIT`, but it can be
|
||||
changed by setting the `spring.test.enclosing.configuration` JVM system property to
|
||||
`OVERRIDE`. Alternatively, the default mode may be set via the
|
||||
<<appendix.adoc#appendix-spring-properties,`SpringProperties`>> mechanism.
|
||||
=====
|
||||
|
||||
The <<testcontext-framework>> honors `@NestedTestConfiguration` semantics for the
|
||||
following annotations.
|
||||
|
||||
* <<spring-testing-annotation-bootstrapwith>>
|
||||
* <<spring-testing-annotation-contextconfiguration>>
|
||||
* <<spring-testing-annotation-webappconfiguration>>
|
||||
* <<spring-testing-annotation-contexthierarchy>>
|
||||
* <<spring-testing-annotation-activeprofiles>>
|
||||
* <<spring-testing-annotation-testpropertysource>>
|
||||
* <<spring-testing-annotation-dynamicpropertysource>>
|
||||
* <<spring-testing-annotation-dirtiescontext>>
|
||||
* <<spring-testing-annotation-testexecutionlisteners>>
|
||||
* <<spring-testing-annotation-recordapplicationevents>>
|
||||
* <<testcontext-tx,`@Transactional`>>
|
||||
* <<spring-testing-annotation-commit>>
|
||||
* <<spring-testing-annotation-rollback>>
|
||||
* <<spring-testing-annotation-sql>>
|
||||
* <<spring-testing-annotation-sqlconfig>>
|
||||
* <<spring-testing-annotation-sqlmergemode>>
|
||||
* <<integration-testing-annotations-testconstructor>>
|
||||
|
||||
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.
|
||||
|
||||
[[integration-testing-annotations-junit-jupiter-enabledif]]
|
||||
== `@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:
|
||||
|
||||
* <<core.adoc#expressions, Spring Expression Language>> (SpEL) expression. For example:
|
||||
`@EnabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")`
|
||||
* Placeholder for a property available in the Spring <<core.adoc#beans-environment, `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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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 {}
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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 {}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
`@EnabledOnMac` is meant only as an example of what is possible. If you have that exact
|
||||
use case, please use the built-in `@EnabledOnOs(MAC)` support in JUnit Jupiter.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
Since JUnit 5.7, JUnit Jupiter also has a condition annotation named `@EnabledIf`. Thus,
|
||||
if you wish to use Spring's `@EnabledIf` support make sure you import the annotation type
|
||||
from the correct package.
|
||||
====
|
||||
|
||||
[[integration-testing-annotations-junit-jupiter-disabledif]]
|
||||
== `@DisabledIf`
|
||||
|
||||
`@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:
|
||||
|
||||
* <<core.adoc#expressions, Spring Expression Language>> (SpEL) expression. For example:
|
||||
`@DisabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")`
|
||||
* Placeholder for a property available in the Spring <<core.adoc#beans-environment, `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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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 {}
|
||||
----
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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 {}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
`@DisabledOnMac` is meant only as an example of what is possible. If you have that exact
|
||||
use case, please use the built-in `@DisabledOnOs(MAC)` support in JUnit Jupiter.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
Since JUnit 5.7, JUnit Jupiter also has a condition annotation named `@DisabledIf`. Thus,
|
||||
if you wish to use Spring's `@DisabledIf` support make sure you import the annotation type
|
||||
from the correct package.
|
||||
====
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
[[integration-testing-annotations-junit4]]
|
||||
= Spring JUnit 4 Testing Annotations
|
||||
|
||||
The following annotations are supported only when used in conjunction with the
|
||||
<<testcontext-junit4-runner, SpringRunner>>, <<testcontext-junit4-rules, Spring's JUnit 4
|
||||
rules>>, or <<testcontext-support-classes-junit4, Spring's JUnit 4 support classes>>:
|
||||
|
||||
* <<integration-testing-annotations-junit4-ifprofilevalue>>
|
||||
* <<integration-testing-annotations-junit4-profilevaluesourceconfiguration>>
|
||||
* <<integration-testing-annotations-junit4-timed>>
|
||||
* <<integration-testing-annotations-junit4-repeat>>
|
||||
|
||||
[[integration-testing-annotations-junit4-ifprofilevalue]]
|
||||
== `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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".
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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.
|
||||
|
||||
|
||||
[[integration-testing-annotations-junit4-profilevaluesourceconfiguration]]
|
||||
== `@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`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ProfileValueSourceConfiguration(CustomProfileValueSource.class) // <1>
|
||||
public class CustomProfileValueSourceTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Use a custom profile value source.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@ProfileValueSourceConfiguration(CustomProfileValueSource::class) // <1>
|
||||
class CustomProfileValueSourceTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Use a custom profile value source.
|
||||
|
||||
|
||||
[[integration-testing-annotations-junit4-timed]]
|
||||
== `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Timed(millis = 1000) // <1>
|
||||
public void testProcessWithOneSecondTimeout() {
|
||||
// some logic that should not take longer than 1 second to run
|
||||
}
|
||||
----
|
||||
<1> Set the time period for the test to one second.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Timed(millis = 1000) // <1>
|
||||
fun testProcessWithOneSecondTimeout() {
|
||||
// some logic that should not take longer than 1 second to run
|
||||
}
|
||||
----
|
||||
<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.
|
||||
|
||||
[[integration-testing-annotations-junit4-repeat]]
|
||||
== `@Repeat`
|
||||
|
||||
`@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
|
||||
<<testcontext-junit4-rules, `SpringMethodRule`>>, the scope additionally includes
|
||||
preparation of the test instance by `TestExecutionListener` implementations. The
|
||||
following example shows how to use the `@Repeat` annotation:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Repeat(10) // <1>
|
||||
@Test
|
||||
public void testProcessRepeatedly() {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Repeat this test ten times.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Repeat(10) // <1>
|
||||
@Test
|
||||
fun testProcessRepeatedly() {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Repeat this test ten times.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
[[integration-testing-annotations-meta]]
|
||||
= Meta-Annotation Support for Testing
|
||||
|
||||
You can use most test-related annotations as
|
||||
<<core.adoc#beans-meta-annotations, 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, 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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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 { }
|
||||
----
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
|
||||
@ActiveProfiles("dev")
|
||||
@Transactional
|
||||
public @interface TransactionalDevTestConfig { }
|
||||
----
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@RunWith(SpringRunner.class)
|
||||
@TransactionalDevTestConfig
|
||||
public class OrderRepositoryTests { }
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@TransactionalDevTestConfig
|
||||
public class UserRepositoryTests { }
|
||||
----
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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 { }
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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 { }
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@TransactionalDevTestConfig
|
||||
class OrderRepositoryTests { }
|
||||
|
||||
@TransactionalDevTestConfig
|
||||
class UserRepositoryTests { }
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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 { }
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@TransactionalIntegrationTest
|
||||
void saveOrder() { }
|
||||
|
||||
@TransactionalIntegrationTest
|
||||
void deleteOrder() { }
|
||||
----
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@TransactionalIntegrationTest
|
||||
fun saveOrder() { }
|
||||
|
||||
@TransactionalIntegrationTest
|
||||
fun deleteOrder() { }
|
||||
----
|
||||
|
||||
For further details, see the
|
||||
https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model[Spring Annotation Programming Model]
|
||||
wiki page.
|
||||
@@ -0,0 +1,29 @@
|
||||
[[integration-testing-annotations-spring]]
|
||||
= 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:
|
||||
|
||||
* <<spring-testing-annotation-bootstrapwith>>
|
||||
* <<spring-testing-annotation-contextconfiguration>>
|
||||
* <<spring-testing-annotation-webappconfiguration>>
|
||||
* <<spring-testing-annotation-contexthierarchy>>
|
||||
* <<spring-testing-annotation-activeprofiles>>
|
||||
* <<spring-testing-annotation-testpropertysource>>
|
||||
* <<spring-testing-annotation-dynamicpropertysource>>
|
||||
* <<spring-testing-annotation-dirtiescontext>>
|
||||
* <<spring-testing-annotation-testexecutionlisteners>>
|
||||
* <<spring-testing-annotation-recordapplicationevents>>
|
||||
* <<spring-testing-annotation-commit>>
|
||||
* <<spring-testing-annotation-rollback>>
|
||||
* <<spring-testing-annotation-beforetransaction>>
|
||||
* <<spring-testing-annotation-aftertransaction>>
|
||||
* <<spring-testing-annotation-sql>>
|
||||
* <<spring-testing-annotation-sqlconfig>>
|
||||
* <<spring-testing-annotation-sqlmergemode>>
|
||||
* <<spring-testing-annotation-sqlgroup>>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
[[spring-testing-annotation-activeprofiles]]
|
||||
= `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
@ActiveProfiles("dev") // <1>
|
||||
class DeveloperTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Indicate that the `dev` profile should be active.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
@ActiveProfiles({"dev", "integration"}) // <1>
|
||||
class DeveloperIntegrationTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Indicate that the `dev` and `integration` profiles should be active.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@ContextConfiguration
|
||||
@ActiveProfiles(["dev", "integration"]) // <1>
|
||||
class DeveloperIntegrationTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Indicate that the `dev` and `integration` 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
|
||||
<<testcontext-ctx-management-env-profiles-ActiveProfilesResolver, `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.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
[[spring-testing-annotation-aftertransaction]]
|
||||
= `@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.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@AfterTransaction // <1>
|
||||
void afterTransaction() {
|
||||
// logic to be run after a transaction has ended
|
||||
}
|
||||
----
|
||||
<1> Run this method after a transaction.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@AfterTransaction // <1>
|
||||
fun afterTransaction() {
|
||||
// logic to be run after a transaction has ended
|
||||
}
|
||||
----
|
||||
<1> Run this method after a transaction.
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
[[spring-testing-annotation-beforetransaction]]
|
||||
= `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@BeforeTransaction // <1>
|
||||
void beforeTransaction() {
|
||||
// logic to be run before a transaction is started
|
||||
}
|
||||
----
|
||||
<1> Run this method before a transaction.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@BeforeTransaction // <1>
|
||||
fun beforeTransaction() {
|
||||
// logic to be run before a transaction is started
|
||||
}
|
||||
----
|
||||
<1> Run this method before a transaction.
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[[spring-testing-annotation-bootstrapwith]]
|
||||
= `@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
|
||||
<<testcontext-bootstrapping, bootstrapping the TestContext framework>> for further details.
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
[[spring-testing-annotation-commit]]
|
||||
= `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Commit // <1>
|
||||
@Test
|
||||
void testProcessWithoutRollback() {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Commit the result of the test to the database.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Commit // <1>
|
||||
@Test
|
||||
fun testProcessWithoutRollback() {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Commit the result of the test to the database.
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
[[spring-testing-annotation-contextconfiguration]]
|
||||
= `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration("/test-config.xml") // <1>
|
||||
class XmlApplicationContextTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Referring to an XML file.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration(classes = TestConfig.class) // <1>
|
||||
class ConfigClassApplicationContextTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Referring to a class.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration(initializers = CustomContextInitializer.class) // <1>
|
||||
class ContextInitializerTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Declaring an initializer class.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@ContextConfiguration(initializers = [CustomContextInitializer::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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration(locations = "/test-context.xml", loader = CustomContextLoader.class) // <1>
|
||||
class CustomLoaderXmlApplicationContextTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Configuring both a location and a custom loader.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@ContextConfiguration("/test-context.xml", loader = CustomContextLoader::class) // <1>
|
||||
class CustomLoaderXmlApplicationContextTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> 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.
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
[[spring-testing-annotation-contexthierarchy]]
|
||||
= `@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):
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextHierarchy({
|
||||
@ContextConfiguration("/parent-config.xml"),
|
||||
@ContextConfiguration("/child-config.xml")
|
||||
})
|
||||
class ContextHierarchyTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@ContextHierarchy(
|
||||
ContextConfiguration("/parent-config.xml"),
|
||||
ContextConfiguration("/child-config.xml"))
|
||||
class ContextHierarchyTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@WebAppConfiguration
|
||||
@ContextHierarchy({
|
||||
@ContextConfiguration(classes = AppConfig.class),
|
||||
@ContextConfiguration(classes = WebConfig.class)
|
||||
})
|
||||
class WebIntegrationTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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
|
||||
{api-spring-framework}/test/context/ContextHierarchy.html[`@ContextHierarchy`] javadoc
|
||||
for further examples.
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
[[spring-testing-annotation-dirtiescontext]]
|
||||
= `@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`.
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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.
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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).
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@DirtiesContext // <1>
|
||||
class ContextDirtyingTests {
|
||||
// some tests that result in the Spring container being dirtied
|
||||
}
|
||||
----
|
||||
<1> Dirty the context after the current test class.
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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.`
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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.
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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.`
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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.
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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`.
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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.
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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).
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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.
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.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.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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
|
||||
{api-spring-framework}/test/annotation/DirtiesContext.HierarchyMode.html[`DirtiesContext.HierarchyMode`]
|
||||
javadoc.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
[[spring-testing-annotation-dynamicpropertysource]]
|
||||
= `@DynamicPropertySource`
|
||||
|
||||
`@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
|
||||
https://www.testcontainers.org/[Testcontainers] project.
|
||||
|
||||
The following example demonstrates how to register a dynamic property:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
class MyIntegrationTests {
|
||||
|
||||
static MyExternalServer server = // ...
|
||||
|
||||
@DynamicPropertySource // <1>
|
||||
static void dynamicProperties(DynamicPropertyRegistry registry) { // <2>
|
||||
registry.add("server.port", server::getPort); // <3>
|
||||
}
|
||||
|
||||
// tests ...
|
||||
}
|
||||
----
|
||||
<1> Annotate a `static` method with `@DynamicPropertySource`.
|
||||
<2> Accept a `DynamicPropertyRegistry` as an argument.
|
||||
<3> Register a dynamic `server.port` property to be retrieved lazily from the server.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@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 ...
|
||||
}
|
||||
----
|
||||
<1> Annotate a `static` method with `@DynamicPropertySource`.
|
||||
<2> Accept a `DynamicPropertyRegistry` as an argument.
|
||||
<3> Register a dynamic `server.port` property to be retrieved lazily from the server.
|
||||
|
||||
See <<testcontext-ctx-management-dynamic-property-sources>> for further details.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[[spring-testing-annotation-recordapplicationevents]]
|
||||
= `@RecordApplicationEvents`
|
||||
|
||||
`@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.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
[[spring-testing-annotation-rollback]]
|
||||
= `@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):
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Rollback(false) // <1>
|
||||
@Test
|
||||
void testProcessWithoutRollback() {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Do not roll back the result.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Rollback(false) // <1>
|
||||
@Test
|
||||
fun testProcessWithoutRollback() {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Do not roll back the result.
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
[[spring-testing-annotation-sql]]
|
||||
= `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Test
|
||||
@Sql({"/test-schema.sql", "/test-user-data.sql"}) // <1>
|
||||
void userTest() {
|
||||
// run code that relies on the test schema and test data
|
||||
}
|
||||
----
|
||||
<1> Run two scripts for this test.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Test
|
||||
@Sql("/test-schema.sql", "/test-user-data.sql") // <1>
|
||||
fun userTest() {
|
||||
// run 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.
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
[[spring-testing-annotation-sqlconfig]]
|
||||
= `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Test
|
||||
@Sql(
|
||||
scripts = "/test-user-data.sql",
|
||||
config = @SqlConfig(commentPrefix = "`", separator = "@@") // <1>
|
||||
)
|
||||
void userTest() {
|
||||
// run code that relies on the test data
|
||||
}
|
||||
----
|
||||
<1> Set the comment prefix and the separator in SQL scripts.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Test
|
||||
@Sql("/test-user-data.sql", config = SqlConfig(commentPrefix = "`", separator = "@@")) // <1>
|
||||
fun userTest() {
|
||||
// run code that relies on the test data
|
||||
}
|
||||
----
|
||||
<1> Set the comment prefix and the separator in SQL scripts.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
[[spring-testing-annotation-sqlgroup]]
|
||||
= `@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@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
|
||||
}
|
||||
----
|
||||
<1> Declare a group of SQL scripts.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@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
|
||||
}
|
||||
----
|
||||
<1> Declare a group of SQL scripts.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
[[spring-testing-annotation-sqlmergemode]]
|
||||
= `@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.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@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
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Set the `@Sql` merge mode to `MERGE` for all test methods in the class.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@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
|
||||
}
|
||||
}
|
||||
----
|
||||
<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.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@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
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Set the `@Sql` merge mode to `MERGE` for a specific test method.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@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
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Set the `@Sql` merge mode to `MERGE` for a specific test method.
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
[[spring-testing-annotation-testexecutionlisteners]]
|
||||
= `@TestExecutionListeners`
|
||||
|
||||
`@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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
@TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class}) // <1>
|
||||
class CustomTestExecutionListenerTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Register two `TestExecutionListener` implementations.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@ContextConfiguration
|
||||
@TestExecutionListeners(CustomTestExecutionListener::class, AnotherTestExecutionListener::class) // <1>
|
||||
class CustomTestExecutionListenerTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> 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>>.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
[[spring-testing-annotation-testpropertysource]]
|
||||
= `@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.
|
||||
|
||||
The following example demonstrates how to declare a properties file from the classpath:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
@TestPropertySource("/test.properties") // <1>
|
||||
class MyIntegrationTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Get properties from `test.properties` in the root of the classpath.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
@TestPropertySource(properties = { "timezone = GMT", "port: 4242" }) // <1>
|
||||
class MyIntegrationTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Declare `timezone` and `port` properties.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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.
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
[[spring-testing-annotation-webappconfiguration]]
|
||||
= `@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:
|
||||
|
||||
--
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration // <1>
|
||||
class WebAppTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> The `@WebAppConfiguration` annotation.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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:
|
||||
|
||||
--
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration("classpath:test-web-resources") // <1>
|
||||
class WebAppTests {
|
||||
// class body...
|
||||
}
|
||||
----
|
||||
<1> Specifying a classpath resource.
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.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
|
||||
{api-spring-framework}/test/context/web/WebAppConfiguration.html[`@WebAppConfiguration`]
|
||||
javadoc for further details.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
[[integration-testing-annotations-standard]]
|
||||
= 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` (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 <<testcontext-tx-attribute-support, limited attribute support>>_
|
||||
|
||||
.JSR-250 Lifecycle Annotations
|
||||
[NOTE]
|
||||
====
|
||||
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`.
|
||||
====
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user