Spring's @Configurable is based upon a static aspect.
Hence you might end up in the following scenario:
- Test1 uses Ctx1
- Test2 uses Ctx2
- Test3 uses Ctx1
- Test1 runs
- Ctx1 is not in the context cache of spring
- Ctx1 is loaded and the aspect is initialized with that context
- Ctx1 is put into the context cache of spring
- Test2 runs
- Ctx2 is not in the context cache of spring
- Ctx2 is loaded and the aspect is initialized with that context
- Ctx2 is put into the context cache of spring
- Test3 runs
- Ctx1 is inside the context cache of spring
- Ctx1 is retrieved from the cache and the aspect is still pointing to Ctx2
We solved this issue by reinitializing the context the aspect is pointing to, by extending the SpringJUnit4ClassRunner and registering a custom TestExecutionListener
package x.y.z;
import org.aspectj.lang.Aspects;
import org.junit.internal.runners.InitializationError;
import org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AbstractTestExecutionListener;
public class MySpringJUnit4ClassRunner extends SpringJUnit4ClassRunner {
public MySpringJUnit4ClassRunner(Class clazz) throws InitializationError {
super(clazz);
getTestContextManager().registerTestExecutionListeners(new AbstractTestExecutionListener() {
@Override
public void prepareTestInstance(TestContext testContext)
throws Exception {
Aspects.aspectOf(AnnotationBeanConfigurerAspect.class).destroy();
Aspects.aspectOf(AnnotationBeanConfigurerAspect.class)
.setBeanFactory(((GenericApplicationContext)testContext.getApplicationContext()).getDefaultListableBeanFactory());
}
});
}
}