-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Andy Wilkinson opened SPR-7964 and commented
We have a perhaps unusual situation where we have a mixture of plain JUnit tests and Spring-powered JUnit tests (annotated to run with SpringJUnit4ClassRunner) in the same project. All of the Spring-powered tests are annotated with @DirtiesContext. The project's compiled with AspectJ and is using Spring's AspectJ-powered transaction support. There are three test classes involved, and a failure occurs if they run in a particular order. In the order:
- Not Spring-powered
- Spring-powered
- Spring-powered
all of the tests will pass.
In the order:
- Spring-powered
- Not Spring-powered
- Spring-powered
the tests will fail.
In the failing case, the test that is not Spring-powered performs some entirely unexpected application context initialization. As this test isn't being run with Spring's runner and isn't annotated with @DirtiesContext, this leaves the application context in an unexpected state which causes the second class of Spring-powered tests to fail.
Crucially, the tests that aren't Spring-powered call a method that is annotated with @Transactional and has therefore been woven with Spring's transaction aspects. When this method is driven, the before advice results in determineTransactionManager() being called on AnnotationTransactionAspect. Unexpectedly AnnotationTransactionAspect has a non-null beanFactory reference so it asks the bean for the transaction manager. It's at this point that the unexpected initialization occurs.
To get to the point (finally!), I believe that the problem is that AnnotationTransactionAspect is being left with a reference to an out-of-date BeanFactory instance. My guess is that setting this reference to null during the cleanup processing triggered by the presence of the @DirtiesContext annotation will fix the problem.
I'm currently working around the failure with the following in the test class that's not Spring-powered:
@BeforeClass
public static void removeBeanFactoryFromAnnotationTransactionAspect() {
AnnotationTransactionAspect.aspectOf().setBeanFactory(null);
}
Further Resources
- Spring Test Context Caching + AspectJ @Transactional + Ehcache pain blog by Java Code Geeks
Affects: 3.0.5
Issue Links:
- TestContext framework should support one AspectJ instance per ApplicationContext [SPR-6353] #11019 TestContext framework should support one AspectJ instance per ApplicationContext
- AnnotationTransactionAspect retains reference to JpaTransactionManager from closed context [SPR-12518] #17123 AnnotationTransactionAspect retains reference to JpaTransactionManager from closed context
1 votes, 4 watchers