-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
Phil Webb opened SPR-9232 and commented
Status Quo
The order in which JUnit rules are run was changed between Spring 3.0 and 3.1 to match JUnit (see #12361). As a side effect of this, @Rule
callbacks (such as the one developed for #11259) are now executed after the callbacks in TestExecutionListeners
. This can be problematic if your rule is running within a transaction as the TransactionalTestExecutionListener
will perform the rollback before the rule runs. The opposite may also be true: a transaction might not be started before the rule runs.
Current Implementation of SpringJUnit4ClassRunner.methodBlock()
Statement statement = methodInvoker(frameworkMethod, testInstance);
statement = possiblyExpectingExceptions(frameworkMethod, testInstance, statement);
statement = withBefores(frameworkMethod, testInstance, statement);
statement = withAfters(frameworkMethod, testInstance, statement);
statement = withRulesReflectively(frameworkMethod, testInstance, statement);
statement = withPotentialRepeat(frameworkMethod, testInstance, statement);
statement = withPotentialTimeout(frameworkMethod, testInstance, statement);
Goals
Ideally, one could argue that in most circumstances the TransactionalTestExecutionListener
should always be the first and last thing to run.
Deliverables
- Consider changing the
SpringJUnit4ClassRunner.methodBlock()
method to callTestExecutionListener
callbacks outside of JUnit@Before
calls, something like:
Statement statement = methodInvoker(frameworkMethod, testInstance);
statement = possiblyExpectingExceptions(frameworkMethod, testInstance, statement);
statement = withTestExecutionListenerBefores(frameworkMethod, testInstance, statement);
statement = withTestExecutionListenerAfters(frameworkMethod, testInstance, statement);
statement = withRulesReflectively(frameworkMethod, testInstance, statement);
statement = withBefores(frameworkMethod, testInstance, statement);
statement = withAfters(frameworkMethod, testInstance, statement);
statement = withPotentialRepeat(frameworkMethod, testInstance, statement);
statement = withPotentialTimeout(frameworkMethod, testInstance, statement);
This would ensure that the before and after callbacks of TransactionalTestExecutionListener
(and any TestExecutionListener
) get called around the @Rule
.
Alternatives
Another option would be to introduce a RuleAwareTestExecutionListener
interface that adds beforeRules()
and afterRules()
methods and have TransactionalTestExecutionListener
implement this interface as well (or possibly instead of) TestExecutionListener
.
Affects: 3.1.1
Issue Links:
- Provide @Rule alternative to SpringJUnit4ClassRunner [SPR-7731] #12387 Provide
@Rule
alternative to SpringJUnit4ClassRunner ("depends on") - jUnit 4 and @Rule execution order [SPR-7705] #12361 jUnit 4 and
@Rule
execution order
4 votes, 6 watchers