2012-07-25 60 views
3

我能夠通過在正常的servlet上下文之外實例化對象來完成Spring MVC控制器上幾乎所有的單元測試。但我希望能夠運行一些測試以確保我的對象序列化工作正常,標題正在生成等。@ExceptionHandler不能使用Spring MVC 3.1單元測試

要在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 Template 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> 
+0

能否請您顯示您的junit-servlet-context.xml文件的內容,以及它與普通Web上下文文件的內容有何不同 – 2012-07-25 12:24:20

+0

junit-servlet-context.xml文件與servlet-context相同.xml文件由Spring Template MVC嚮導創建,只有一個例外:添加了一個排除過濾器,該過濾器阻止初始化控制器使用的某些bean的@Component的實例化。我已將它添加到主帖子中。 – Mark 2012-07-25 13:31:41

回答

1

恐怕你將不得不看spring-test-mvc,原因是從控制器異常,並使用ExceptionResolver調用適當的@ExceptionHandler的處理在DispatcherServlet,不HandlerAdapter水平完成。你的測試開始於HandlerAdapter

雖然我強烈建議spring-test-mvc,但我一直在使用它一段時間,並沒有看到我的場景有任何問題 - http://biju-allandsundry.blogspot.com/2012/07/spring-mvc-integration-tests.html

一種異常流量測試是這樣的帶彈簧的測試-MVC:

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"; 
} 

}

在上下文中加載調度的servlet
xmlConfigSetup("classpath:/META-INF/spring/web/webmvc-config.xml") 
    .configureWebAppRootDir("src/main/webapp", false).build() 
    .perform(get("/contexts/exception")) 
    .andExpect(status().isOk()) 
    .andExpect(view().name("exceptionPage")); 
+0

謝謝,我有點擔心這個問題與HandlerAdapter有關。我會看看我是否可以通過spring-test-mvc獲得一些牽引力。這並不是說我看到了任何重大問題,但我並不太樂意在一些仍處於發展中的事情上進行大筆投資。考慮到我對Spring非常陌生,採用少量記錄的工具是一個很大的嘗試。 – Mark 2012-07-26 01:23:56

3

添加下面的類一旦你完成了使用

@ContextConfiguration(locations = {"classpath:app-config.xml",loader = MockWebApplicationContext.class) 

在測試類上使用Autowired註釋加載DispatcherServlet。處理它使用

servlet.service(request,response); 

現在它應該也處理異常流。

雖然它可能需要3.1.2。

+0

嘿@vivekd,我到底在哪裏把這個servlet.service(請求,響應); ??謝謝 – renanlf 2013-07-26 21:46:59