Wednesday, February 24, 2010

Testing request- and session-scoped spring beans with JUnit

I recently updated my web app to use a UserDetails bean that has request scope. Then I found out that my integration tests didn't work.

java.lang.IllegalStateException: No Scope registered for scope 'request'
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
 at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
 at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.getTarget(Cglib2AopProxy.java:657)
 at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:608)
...

The Spring Documentation made it quite clear:
The request, session, and global session scopes are only available if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers such as the ClassPathXmlApplicationContext, you get an IllegalStateException complaining about an unknown bean scope.

I looked for solutions, and found Thomas Webner's and Andreas Höhmann's, but they weren't really what I wanted. After a bit of messing around, I found that it was easiest to continue using the existing ApplicationContext (which was actually a GenericApplicationContext, not web-aware), and to add a "request" scope to it. This may not be sufficient once I do more complex tests, but it seems ok for now.

   @Before
   public void setupRequestScope() {
      if (applicationContext instanceof GenericApplicationContext) {
         GenericApplicationContext context = (GenericApplicationContext) applicationContext;
         ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
         Scope requestScope = new SimpleThreadScope();
         beanFactory.registerScope("request", requestScope);
      }
   }