Support parameter injection in @[Before|After]Transaction methods

Prior to this commit, @​BeforeTransaction and @​AfterTransaction
methods could not accept any arguments. This is acceptable with testing
frameworks such as JUnit 4 and TestNG that do not provide support for
parameter injection. However, users of JUnit Jupiter have become
accustomed to being able to accept arguments in lifecycle methods
annotated with JUnit's @​BeforeEach, @​AfterEach, etc.

As a follow up to the previous commit (see gh-31199), this commit
introduces first-class support for parameter injection in
@​BeforeTransaction and @​AfterTransaction methods, as demonstrated in
the following example.

@​BeforeTransaction
void verifyInitialDatabaseState(@Autowired DataSource dataSource) {
	// Use the DataSource to verify the initial DB state
}

Closes gh-30736
This commit is contained in:
Sam Brannen
2023-09-10 14:35:24 +02:00
parent 41904d46ad
commit ed83461021
6 changed files with 187 additions and 22 deletions

View File

@@ -177,7 +177,7 @@ following features above and beyond the feature set that Spring supports for JUn
TestNG:
* Dependency injection for test constructors, test methods, and test lifecycle callback
methods. See xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-di[Dependency Injection with `SpringExtension`] for further details.
methods. See xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-di[Dependency Injection with the `SpringExtension`] for further details.
* Powerful support for link:https://junit.org/junit5/docs/current/user-guide/#extensions-conditions[conditional
test execution] based on SpEL expressions, environment variables, system properties,
and so on. See the documentation for `@EnabledIf` and `@DisabledIf` in
@@ -310,17 +310,19 @@ See the documentation for `@SpringJUnitConfig` and `@SpringJUnitWebConfig` in
xref:testing/annotations/integration-junit-jupiter.adoc[Spring JUnit Jupiter Testing Annotations] for further details.
[[testcontext-junit-jupiter-di]]
=== Dependency Injection with `SpringExtension`
=== Dependency Injection with the `SpringExtension`
`SpringExtension` implements the
The `SpringExtension` implements the
link:https://junit.org/junit5/docs/current/user-guide/#extensions-parameter-resolution[`ParameterResolver`]
extension API from JUnit Jupiter, which lets Spring provide dependency injection for test
constructors, test methods, and test lifecycle callback methods.
Specifically, `SpringExtension` can inject dependencies from the test's
`ApplicationContext` into test constructors and methods that are annotated with
`@BeforeAll`, `@AfterAll`, `@BeforeEach`, `@AfterEach`, `@Test`, `@RepeatedTest`,
`@ParameterizedTest`, and others.
Specifically, the `SpringExtension` can inject dependencies from the test's
`ApplicationContext` into into test constructors and methods that are annotated with
Spring's `@BeforeTransaction` and `@AfterTransaction` or JUnit's `@BeforeAll`,
`@AfterAll`, `@BeforeEach`, `@AfterEach`, `@Test`, `@RepeatedTest`, `@ParameterizedTest`,
and others.
[[testcontext-junit-jupiter-di-constructor]]
==== Constructor Injection

View File

@@ -298,6 +298,44 @@ method in a test class or any `void` default method in a test interface with one
annotations, and the `TransactionalTestExecutionListener` ensures that your
before-transaction method or after-transaction method runs at the appropriate time.
[NOTE]
====
Generally speaking, `@BeforeTransaction` and `@AfterTransaction` methods must not accept
any arguments.
However, as of Spring Framework 6.1, for tests using the
xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-extension[`SpringExtension`]
with JUnit Jupiter, `@BeforeTransaction` and `@AfterTransaction` methods may optionally
accept arguments which will be resolved by any registered JUnit `ParameterResolver`
extension such as the `SpringExtension`. This means that JUnit-specific arguments like
`TestInfo` or beans from the test's `ApplicationContext` may be provided to
`@BeforeTransaction` and `@AfterTransaction` methods, as demonstrated in the following
example.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@BeforeTransaction
void verifyInitialDatabaseState(@Autowired DataSource dataSource) {
// Use the DataSource to verify the initial state before a transaction is started
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@BeforeTransaction
fun verifyInitialDatabaseState(@Autowired dataSource: DataSource) {
// Use the DataSource to verify the initial state before a transaction is started
}
----
======
====
[TIP]
====
Any before methods (such as methods annotated with JUnit Jupiter's `@BeforeEach`) and any