-
Notifications
You must be signed in to change notification settings - Fork 38.9k
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 callTestExecutionListenercallbacks outside of JUnit@Beforecalls, 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
@Rulealternative to SpringJUnit4ClassRunner ("depends on") - jUnit 4 and @Rule execution order [SPR-7705] #12361 jUnit 4 and
@Ruleexecution order
4 votes, 6 watchers