Testing Request- and Session-scoped Beans

Spring 自早期就开始支持 Request- and session-scoped beans ,并且你可以通过按照以下步骤测试你的请求作用域和会话作用域 bean:

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

以下代码段显示了登录用例的 XML 配置。请注意,userService bean 依赖于基于请求的 loginAction bean。此外,LoginAction 是通过使用 SpEL expressions 实例化的,后者从当前 HTTP 请求中检索用户名和密码。在我们的测试中,我们希望通过 TestContext 框架管理的模拟配置这些请求参数。以下清单显示了此用例的配置:

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>

RequestScopedBeanTests 中,我们将 UserService(即测试主题)和 MockHttpServletRequest 都注入到我们的测试实例中。在我们的 requestScope() 测试方法中,我们通过在提供的 MockHttpServletRequest 中设置请求参数来设置我们的测试装置。当 loginUser() 方法在我们的 userService 上调用时,我们确信用户服务可以访问当前 MockHttpServletRequest 的请求范围 loginAction(即,我们刚刚在其中设置参数的那个)。然后,我们可以基于用户名和密码的已知输入对结果执行断言。以下列表显示了如何执行此操作:

In RequestScopedBeanTests, we inject both the UserService (that is, the subject under test) and the MockHttpServletRequest into our test instance. Within our requestScope() test method, we set up our test fixture by setting request parameters in the provided MockHttpServletRequest. 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 MockHttpServletRequest (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

  • Kotlin

@SpringJUnitWebConfig
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
	}
}
@SpringJUnitWebConfig
class RequestScopedBeanTests {

	@Autowired lateinit var userService: UserService
	@Autowired lateinit var request: MockHttpServletRequest

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

		val results = userService.loginUser()
		// assert results
	}
}

以下代码片段类似于我们之前看到的请求范围 Bean 的代码片段。但是,这次 userService Bean 依赖于会话范围的 userPreferences Bean。请注意,UserPreferences Bean 通过使用从当前 HTTP 会话中检索主题的 SpEL 表达式实例化。在我们的测试中,我们需要在 TestContext 框架管理的模拟会话中配置一个主题。以下示例显示了如何执行此操作:

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>

SessionScopedBeanTests 中,我们将 UserServiceMockHttpSession 注入到我们的测试实例中。在我们 sessionScope() 测试方法中,我们通过设置所提供的 MockHttpSession 中预期的 theme 属性来设置我们的测试装置。当 processUserPreferences() 方法在我们的 userService 上被调用时,我们确保用户服务有权访问当前 MockHttpSession 的会话范围的 userPreferences,并且我们可以基于经过配置的主题对结果执行断言。以下示例展示了如何执行此操作:

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

  • Kotlin

@SpringJUnitWebConfig
class SessionScopedBeanTests {

	@Autowired UserService userService;
	@Autowired MockHttpSession session;

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

		Results results = userService.processUserPreferences();
		// assert results
	}
}
@SpringJUnitWebConfig
class SessionScopedBeanTests {

	@Autowired lateinit var userService: UserService
	@Autowired lateinit var session: MockHttpSession

	@Test
	fun sessionScope() {
		session.setAttribute("theme", "blue")

		val results = userService.processUserPreferences()
		// assert results
	}
}