Testing Request- and Session-scoped Beans

Infra has supported Request- and session-scoped beans since the early years, and you can test your request-scoped and session-scoped beans by following these steps:

  • Ensure that a WebApplicationContext is loaded for your test by annotating your test class with @WebAppConfiguration.

  • Inject the mock request or session into your test instance and prepare your test fixture as appropriate.

  • Invoke your web component that you retrieved from the configured WebApplicationContext (with dependency injection).

  • Perform assertions against the mocks.

The next code snippet shows the XML configuration for a login use case. Note that the userService bean has a dependency on a request-scoped loginAction bean. Also, the LoginAction is instantiated by using SpEL expressions that retrieve the username and password from the current HTTP request. In our test, we want to configure these request parameters through the mock managed by the TestContext framework. The following listing shows the configuration for this use case:

Request-scoped bean configuration
<beans>

  <bean id="userService" class="com.example.SimpleUserService"
      c:loginAction-ref="loginAction"/>

  <bean id="loginAction" class="com.example.LoginAction"
      c:username="#{request.getParameter('user')}"
      c:password="#{request.getParameter('pswd')}"
      scope="request">
    <aop:scoped-proxy/>
  </bean>

</beans>

In RequestScopedBeanTests, we inject both the UserService (that is, the subject under test) and the HttpMockRequestImpl into our test instance. Within our requestScope() test method, we set up our test fixture by setting request parameters in the provided HttpMockRequestImpl. When the loginUser() method is invoked on our userService, we are assured that the user service has access to the request-scoped loginAction for the current HttpMockRequestImpl (that is, the one in which we just set parameters). We can then perform assertions against the results based on the known inputs for the username and password. The following listing shows how to do so:

  • Request-scoped bean test

@JUnitWebConfig
class RequestScopedBeanTests {

  @Autowired UserService userService;
  @Autowired MockHttpServletRequest request;

  @Test
  void requestScope() {
    request.setParameter("user", "enigma");
    request.setParameter("pswd", "$pr!ng");

    LoginResults results = userService.loginUser();
    // assert results
  }
}

The following code snippet is similar to the one we saw earlier for a request-scoped bean. However, this time, the userService bean has a dependency on a session-scoped userPreferences bean. Note that the UserPreferences bean is instantiated by using a SpEL expression that retrieves the theme from the current HTTP session. In our test, we need to configure a theme in the mock session managed by the TestContext framework. The following example shows how to do so:

Session-scoped bean configuration
<beans>

  <bean id="userService" class="com.example.SimpleUserService"
      c:userPreferences-ref="userPreferences" />

  <bean id="userPreferences" class="com.example.UserPreferences"
      c:theme="#{session.getAttribute('theme')}"
      scope="session">
    <aop:scoped-proxy/>
  </bean>

</beans>

In SessionScopedBeanTests, we inject the UserService and the MockHttpSession into our test instance. Within our sessionScope() test method, we set up our test fixture by setting the expected theme attribute in the provided MockHttpSession. When the processUserPreferences() method is invoked on our userService, we are assured that the user service has access to the session-scoped userPreferences for the current MockHttpSession, and we can perform assertions against the results based on the configured theme. The following example shows how to do so:

  • Session-scoped bean test

@JUnitWebConfig
class SessionScopedBeanTests {

  @Autowired UserService userService;
  @Autowired MockHttpSession session;

  @Test
  void sessionScope() throws Exception {
    session.setAttribute("theme", "blue");

    Results results = userService.processUserPreferences();
    // assert results
  }
}