@ExceptionHandler无法与Spring MVC 3.1单元测试一起使用
作者:互联网
通过实例化普通servlet上下文之外的对象,我几乎可以在Spring MVC控制器上进行所有的单元测试.但是我希望能够运行一些测试以确保我的对象序列化工作正常,正在生成标头等.
为了在servlet上下文中运行测试,我创建了一个修改后的上下文文件,这样就不会构造各种bean,然后在我的测试用例中使用EasyMock创建这些bean的模拟版本.然后,我用这样的代码调用我的处理程序,并从MockHttpServletResponse中获取大部分所需信息.
我认为这就是它的本质:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:root-context.xml",
"file:junit-servlet-context.xml" } )
public class HomeControllerConfigHandlerHttp {
@Autowired
private RequestMappingHandlerAdapter handlerAdapter;
@Autowired
private RequestMappingHandlerMapping handlerMapping;
... //miscellaneous setup
public void someTest() throws Exception
{
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setRequestURI("/config");
request.addParameter("foo", "bar");
request.addParameter("device", "oakmont");
MockHttpServletResponse response = new MockHttpServletResponse();
Object handler = handlerMapping.getHandler(request).getHandler();
replay(dblient);
expect(serviceClient.checkDevice("oakmont")).andReturn( true );
serviceClient.destroy();
replay(serviceClient);
ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);
String content = new String( response.getContentAsByteArray() );
Assert.assertEquals(content, "Expected configuration");
String content_type = response.getHeader("Content-type");
Assert.assertEquals( content_type, "text/plain");
int status = response.getStatus();
Assert.assertEquals(status, 200 );
这可以达到我的预期,但是有一个问题.我使用@ExceptionHandler在控制器中进行了大量错误处理.这是在任何处理程序中退出错误情况的简单方法,它为我提供了一种一致的公开错误的方法.
@ExceptionHandler在正常的servlet部署中工作正常,但是在此单元测试模型中,当我引发异常时不会调用它.进入Spring代码对我来说是个挑战,因为我是新手,所以很快就迷路了.但是,在普通的servlet环境中,看起来好像有一个异常处理程序正在寻找带注释的处理程序.在SpringJUnit4ClassRunner下运行时,异常的处理方式不同.
如果有办法解决这个问题,我想做.由于缺乏开拓精神,我避免使用spring-test-mvc,但是如果有人告诉我它可以很好地解决这一问题,我将尝试使用它.
我的junit-servlet-context.xml文件的内容与Spring模板MVC向导创建的servlet-context.xml文件几乎相同.唯一的区别是添加了一个排除过滤器,该过滤器用于防止实例化@Component的实例创建由我的控制器使用的几个单例.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.cisco.onplus.home.dmz" >
<context:exclude-filter type="regex" expression=".*InitDatabase.*"/>
</context:component-scan>
</beans:beans>
解决方法:
添加以下类以在上下文中加载Dispatcher servlet:
public class MockWebApplicationContext extends AbstractContextLoader {
@Override
public ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) throws Exception {
String[] locations = mergedContextConfiguration.getLocations();
return loadContext(locations);
}
@Override
public ApplicationContext loadContext(String... locations) throws Exception {
XmlWebApplicationContext webApplicationContext = new XmlWebApplicationContext();
webApplicationContext.setConfigLocations(locations);
webApplicationContext.setServletContext(new MockServletContext(new FileSystemResourceLoader() ) );
ServletConfig config = new MockServletConfig();
config.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext);
final DispatcherServlet servlet = new DispatcherServlet(webApplicationContext);
webApplicationContext.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.registerResolvableDependency(DispatcherServlet.class, servlet);
}
});
webApplicationContext.refresh();
servlet.init(config);
return webApplicationContext;
}
@Override
protected String getResourceSuffix() {
return ".xml";
}
}
完成使用后
@ContextConfiguration(locations = {"classpath:app-config.xml",loader = MockWebApplicationContext.class)
在测试类上使用Autowired注释加载DispatcherServlet.使用处理
servlet.service(request,response);
现在它也应该处理异常流.
不过可能需要3.1.2.
标签:unit-testing,spring-3,spring,spring-mvc 来源: https://codeday.me/bug/20191101/1980679.html