Pregunta

I have a session scoped bean which holds user data per http session. I would like to write a Junit test case to test the session scoped bean. I would like to write the test case such that it can prove that the beans are getting created per session. Any pointer as how to write such Junit test case?

¿Fue útil?

Solución

In order to use request and session scopes in unit test you need to:

  • register these scopes in application context
  • create mock session and request
  • register mock request via RequestContextHolder

Something like this (assume that you use Spring TestContext to run your tests): abstractSessionTest.xml:

<beans ...>
    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="session">
                    <bean class="org.springframework.web.context.request.SessionScope" />
                </entry>
                <entry key="request">
                    <bean class="org.springframework.web.context.request.RequestScope" />
                </entry>
            </map>
        </property>
    </bean>
</beans>

.

@ContextConfiguration("abstractSessionTest.xml")
public abstract class AbstractSessionTest {
    protected MockHttpSession session;
    protected MockHttpServletRequest request;

    protected void startSession() {
        session = new MockHttpSession();
    }

    protected void endSession() {
        session.clearAttributes();
        session = null;
    }

    protected void startRequest() {
        request = new MockHttpServletRequest();
        request.setSession(session);
        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
    }

    protected void endRequest() {
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).requestCompleted();
        RequestContextHolder.resetRequestAttributes();
        request = null;
    }
}

Now you can use these methods in your test code:

startSession();
startRequest();
// inside request
endRequest();
startRequest();
// inside another request of the same session
endRequest();
endSession();

Otros consejos

I came across this simpler approach, thought I might as well post here in case others need it.

<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>

With this approach, you don't have to mock any request/session objects.

Source: http://tarunsapra.wordpress.com/2011/06/28/junit-spring-session-and-request-scope-beans/

Spring 3.2 and newer provides support for session/request scoped beans for integration testing

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@WebAppConfiguration
public class SampleTest {

    @Autowired WebApplicationContext wac;

    @Autowired MockHttpServletRequest request;

    @Autowired MockHttpSession session;    

    @Autowired MySessionBean mySessionBean;

    @Autowired MyRequestBean myRequestBean;

    @Test
    public void requestScope() throws Exception {
        assertThat(myRequestBean)
           .isSameAs(request.getAttribute("myRequestBean"));
        assertThat(myRequestBean)
           .isSameAs(wac.getBean("myRequestBean", MyRequestBean.class));
    }

    @Test
    public void sessionScope() throws Exception {
        assertThat(mySessionBean)
           .isSameAs(session.getAttribute("mySessionBean"));
        assertThat(mySessionBean)
           .isSameAs(wac.getBean("mySessionBean", MySessionBean.class));
    }
}

References:

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top