Skip to content

Commit c5ecc50

Browse files
committedMar 6, 2025
Document wrapping behavior for TestExecutionListener callbacks
Closes gh-34422
1 parent 0fd94f1 commit c5ecc50

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed
 

Diff for: ‎spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java

+43
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,35 @@
4242
* {@link org.springframework.core.annotation.Order @Order} annotation. See
4343
* {@link TestContextBootstrapper#getTestExecutionListeners()} for details.
4444
*
45+
* <h3>Wrapping Behavior for Listeners</h3>
46+
*
47+
* <p>The {@link TestContextManager} guarantees <em>wrapping</em> behavior for
48+
* multiple registered listeners that implement lifecycle callbacks such as
49+
* {@link #beforeTestClass(TestContext) beforeTestClass},
50+
* {@link #afterTestClass(TestContext) afterTestClass},
51+
* {@link #beforeTestMethod(TestContext) beforeTestMethod},
52+
* {@link #afterTestMethod(TestContext) afterTestMethod},
53+
* {@link #beforeTestExecution(TestContext) beforeTestExecution}, and
54+
* {@link #afterTestExecution(TestContext) afterTestExecution}. This means that,
55+
* given two listeners {@code Listener1} and {@code Listener2} with {@code Listener1}
56+
* registered before {@code Listener2}, any <em>before</em> callbacks implemented
57+
* by {@code Listener1} are guaranteed to be invoked <strong>before</strong> any
58+
* <em>before</em> callbacks implemented by {@code Listener2}. Similarly, given
59+
* the same two listeners registered in the same order, any <em>after</em>
60+
* callbacks implemented by {@code Listener1} are guaranteed to be invoked
61+
* <strong>after</strong> any <em>after</em> callbacks implemented by
62+
* {@code Listener2}. {@code Listener1} is therefore said to <em>wrap</em>
63+
* {@code Listener2}.
64+
*
65+
* <p>For a concrete example, consider the relationship between the
66+
* {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener
67+
* TransactionalTestExecutionListener} and the
68+
* {@link org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener
69+
* SqlScriptsTestExecutionListener}. The {@code SqlScriptsTestExecutionListener}
70+
* is registered after the {@code TransactionalTestExecutionListener}, so that
71+
* SQL scripts are executed within a transaction managed by the
72+
* {@code TransactionalTestExecutionListener}.
73+
*
4574
* <h3>Registering TestExecutionListener Implementations</h3>
4675
*
4776
* <p>A {@code TestExecutionListener} can be registered explicitly for a test class,
@@ -101,6 +130,8 @@ public interface TestExecutionListener {
101130
* the class.
102131
* <p>This method should be called immediately before framework-specific
103132
* <em>before class</em> lifecycle callbacks.
133+
* <p>See the {@linkplain TestExecutionListener class-level documentation}
134+
* for details on wrapping behavior for lifecycle callbacks.
104135
* <p>The default implementation is <em>empty</em>. Can be overridden by
105136
* concrete classes as necessary.
106137
* @param testContext the test context for the test; never {@code null}
@@ -119,6 +150,8 @@ default void beforeTestClass(TestContext testContext) throws Exception {
119150
* {@link org.springframework.test.context.junit4.rules.SpringMethodRule
120151
* SpringMethodRule}). In any case, this method must be called prior to any
121152
* framework-specific lifecycle callbacks.
153+
* <p>See the {@linkplain TestExecutionListener class-level documentation}
154+
* for details on wrapping behavior for listeners.
122155
* <p>The default implementation is <em>empty</em>. Can be overridden by
123156
* concrete classes as necessary.
124157
* @param testContext the test context for the test; never {@code null}
@@ -138,6 +171,8 @@ default void prepareTestInstance(TestContext testContext) throws Exception {
138171
* this method might be something like {@code beforeTestSetUp} or
139172
* {@code beforeEach}; however, it is unfortunately impossible to rename
140173
* this method due to backward compatibility concerns.
174+
* <p>See the {@linkplain TestExecutionListener class-level documentation}
175+
* for details on wrapping behavior for lifecycle callbacks.
141176
* <p>The default implementation is <em>empty</em>. Can be overridden by
142177
* concrete classes as necessary.
143178
* @param testContext the test context in which the test method will be
@@ -157,6 +192,8 @@ default void beforeTestMethod(TestContext testContext) throws Exception {
157192
* or logging purposes.
158193
* <p>This method <strong>must</strong> be called after framework-specific
159194
* <em>before</em> lifecycle callbacks.
195+
* <p>See the {@linkplain TestExecutionListener class-level documentation}
196+
* for details on wrapping behavior for lifecycle callbacks.
160197
* <p>The default implementation is <em>empty</em>. Can be overridden by
161198
* concrete classes as necessary.
162199
* @param testContext the test context in which the test method will be
@@ -177,6 +214,8 @@ default void beforeTestExecution(TestContext testContext) throws Exception {
177214
* or logging purposes.
178215
* <p>This method <strong>must</strong> be called before framework-specific
179216
* <em>after</em> lifecycle callbacks.
217+
* <p>See the {@linkplain TestExecutionListener class-level documentation}
218+
* for details on wrapping behavior for lifecycle callbacks.
180219
* <p>The default implementation is <em>empty</em>. Can be overridden by
181220
* concrete classes as necessary.
182221
* @param testContext the test context in which the test method will be
@@ -201,6 +240,8 @@ default void afterTestExecution(TestContext testContext) throws Exception {
201240
* this method might be something like {@code afterTestTearDown} or
202241
* {@code afterEach}; however, it is unfortunately impossible to rename
203242
* this method due to backward compatibility concerns.
243+
* <p>See the {@linkplain TestExecutionListener class-level documentation}
244+
* for details on wrapping behavior for lifecycle callbacks.
204245
* <p>The default implementation is <em>empty</em>. Can be overridden by
205246
* concrete classes as necessary.
206247
* @param testContext the test context in which the test method was
@@ -218,6 +259,8 @@ default void afterTestMethod(TestContext testContext) throws Exception {
218259
* the class.
219260
* <p>This method should be called immediately after framework-specific
220261
* <em>after class</em> lifecycle callbacks.
262+
* <p>See the {@linkplain TestExecutionListener class-level documentation}
263+
* for details on wrapping behavior for lifecycle callbacks.
221264
* <p>The default implementation is <em>empty</em>. Can be overridden by
222265
* concrete classes as necessary.
223266
* @param testContext the test context for the test; never {@code null}

0 commit comments

Comments
 (0)