其他分享
首页 > 其他分享> > @ExceptionHandler无法与Spring MVC 3.1单元测试一起使用

@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