April 15, 2011

How to test Spring session scoped beans

I wanted to use the http session just as a repository (database/files), to keep facebook access token for currently logged user. While I can manipulate session directly, another option is to declare the class as a session scoped bean in Spring. Something like this:

public class RepositoryOnHttpSession {
    private String facebookAccessToken;

    public FacebookTemplate getFacebookTemplate() {
        return new FacebookTemplate(facebookAccessToken);
    }

    public void setFacebookAccessToken(String facebookAccessToken) {
        this.facebookAccessToken = facebookAccessToken;
    }    
}
<bean id="repositoryOnHttpSession" class="pl.touk.storytelling.infrastructure.repositories.RepositoryOnHttpSession" scope="session">
    <aop:scoped-proxy/>
</bean>
<aop:scoped-proxy/> makes Spring IoC container create a cglib proxy, and inject that to other singleton type beans instead. All nice and cool, except integration tests (which get Spring IoC container to inject all the dependencies) are blowing up with:

java.lang.IllegalStateException: No Scope registered for scope 'session'

While there's a lot of solutions to be googled (including redeclaring the object as a prototype/sinlgeton for test context, injecting mock http session and request), the easiest way to have a simple thread-bound session scope is just to declare it in the TEST IoC configuration, like below. Just keep in mind that junit fires all tests in a single thread by default, so the state is persisted between tests. You may need to clean it up in @After.
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="session">
                <bean class="org.springframework.context.support.SimpleThreadScope"/>
            </entry>
        </map>
    </property>
</bean>

7 comments:

  1. Thanks, a lot Jakub, for your elegant solution, this helped in my current project (where we also required the 'request' scope).

    ReplyDelete
  2. thanks a lot.. the code was helpful for me.. i solved my problem that i was facing in my project..

    Glenn Drew….
    Error 193 0xc1

    ReplyDelete
  3. thanks so much. worked great for 'request' scope also.

    ReplyDelete
  4. Hi jakub,

    as i am new to spring , i am not sure where to put the CustomScopeConfigurer bean , right now i put that in ,my spring context file ....but it didnt work for me .. do i need to put at the same place where I had marked my beans scope as "request"..

    Any insight will be really helpful

    ReplyDelete
  5. I love this post....... Million thanks life saver!

    ReplyDelete