2008/03/13からのアクセス回数 16482
Spring 2.0から導入されたsession scopeオブジェクトは、DispatcherServletで処理されるため MockHttpServletRequestを使った単体テストでは、bean定義ファイルでscope="session"で 定義されたsession scopeオブジェクトのsession単位での持ち回りのテストができません。
session scopeオブジェクトのテストには、
GenericWebApplicationContextをcreateApplicationContextメソッドで返すTestCaseとして AbstractTransactionalSpringWebContextTestsを追加しました。
AbstractTransactionalSpringWebContextTestsのcreateApplicationContextは以下の通りです。
protected ConfigurableApplicationContext createApplicationContext(final String[] locations) {
GenericWebApplicationContext context =
new GenericWebApplicationContext(
new GenericApplicationContext().getDefaultListableBeanFactory());
context.setServletContext(new MockServletContext());
customizeBeanFactory(context.getDefaultListableBeanFactory());
createBeanDefinitionReader(context).loadBeanDefinitions(locations);
context.refresh();
// StaticWebApplicationContext のpostProcessBeanFactoryと同じ処理を追加
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION,
new SessionScope(true));
return context;
}
HTTPリクエストの前後にRequestContextFilterと同様の処理行うメソッド、beginRequest, endRequestメソッドをAbstractTransactionalSpringWebContextTestsに定義しました。
beginRequestメソッドは、
public void beginRequest(MockHttpServletRequest req) {
ServletRequestAttributes attributes = new ServletRequestAttributes(req);
req.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
RequestContextHolder.setRequestAttributes(attributes);
ServletContext sc = req.getSession().getServletContext();
GenericWebApplicationContext wac = (GenericWebApplicationContext)getApplicationContext();
wac.setServletContext(sc);
sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, (GenericWebApplicationContext)getApplicationContext());
}
endRequestメソッドは、
public void endRequest(MockHttpServletRequest req) {
ServletRequestAttributes attributes = (ServletRequestAttributes) req
.getAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE);
ServletRequestAttributes threadAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
if (threadAttributes != null) {
// We're assumably within the original request thread...
if (attributes == null) {
attributes = threadAttributes;
}
RequestContextHolder.setRequestAttributes(null);
LocaleContextHolder.setLocale(null);
}
if (attributes != null) {
attributes.requestCompleted();
if (logger.isDebugEnabled()) {
logger.debug("Cleared thread-bound request context: " + req);
}
}
}
と定義しました。
session scopeオブジェクトのテストメソッドを定義するには、
以下にMemberOpsControllerを例にHTTP要求の前後処理の仕方を示します。
MemberOpsController memberOpsController =
(MemberOpsController)getApplicationContext().getBean("memberOpsController");
ModelAndView mv = null;
beginRequest(req);
mv = memberOpsController.handleRequest(req,new MockHttpServletResponse());
endRequest(req);
同一セッションは、つぎのようにして持ち回ることができます。
HttpSession session = req.getSession();
req = new MockHttpServletRequest("POST","memberops/list.htm");
req.setSession(session);
これで、session scopeオブジェクトの単体テストができるようになります。
この記事は、
皆様のご意見、ご希望をお待ちしております。