2012-10-08 64 views
1

在Spring的早期版本(3.0)中,可以使用ApplicationContext中的RequestMappingHandlerAdapter和HandlerMapping對象,通過正確的URL測試控制器。但是,在Spring 3.1中,事情發生了變化,我用來使這個工作的代碼不再起作用。有了Spring 3.1,你如何測試你的控制器的URL?

你如何在Spring 3.1中測試Spring控制器url?例如,我想編寫的代碼,如下所示:

ModelAndView modelAndView = handle("GET", "/businesses"); 

這樣,我測試我的映射除了控制器的行動邏輯。

特別是,我最感興趣的是確保我可以傳遞會話屬性,並讓它們正確傳遞給我的控制器操作的@Valid註釋。

有什麼辦法可以用Spring 3.1來完成這個任務嗎?

這是我使用的代碼:

protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response) throws Exception { 
    final HandlerMapping handlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class); 

    final HandlerExecutionChain handler = handlerMapping.getHandler(request); 
    assertNotNull("No handler found for request, check you request mapping", handler); 

    final Object controller = handler.getHandler(); 

    final HandlerInterceptor[] interceptors = handlerMapping.getHandler(request).getInterceptors(); 
    for (HandlerInterceptor interceptor : interceptors) { 
     final boolean carryOn = interceptor.preHandle(request, response, controller); 
     if (!carryOn) { 
      return null; 
     } 
    } 

    return handlerAdapter.handle(request, response, controller); 
} 

protected ModelAndView handle(String method, String path, String queryString) throws Exception { 
    request.setMethod(method); 
    request.setRequestURI(path); 

    if(queryString != null) { 
     String[] parameters = queryString.split("&"); 
     for(String parameter : parameters) { 
      String[] pair = parameter.split("="); 
      if(pair.length == 2) { 
       request.setParameter(pair[0], pair[1]); 
      } else { 
       request.setParameter(pair[0], ""); 
      } 
     } 
    } 

    return handle(request, response); 
} 

protected ModelAndView handle(String method, String path, String attribute, Object object) throws Exception { 
    MockHttpSession session = new MockHttpSession(); 
    session.setAttribute(attribute, object); 
    request.setSession(session); 

    return handle(method, path, null); 
} 

protected ModelAndView handle(String method, String path) throws Exception { 
    return handle(method, path, null); 
} 

protected void assertContentType(ModelAndView modelAndView, String contentType) { 
    assertEquals(contentType, modelAndView.getView().getContentType()); 
} 

回答

1

讓我反而建議spring-test-mvc這是目前在1.0.0M1,但計劃與新的Spring MVC版本的包裝。它應該能夠處理你正在尋找非常容易的情況下,你的測試最終會看起來像這樣:

xmlConfigSetup("classpath:/META-INF/spring/web/webmvc-config.xml") 
      .configureWebAppRootDir("src/main/webapp", false).build() 
      .perform(get("/businesses").param("name", "param1")) 
      .andExpect(status().isOk()) 
      .andExpect(view().name("viewname")); 

您的測試確實爲3.1看起來合適的,所以如果你仍想繼續你的方法你能指出什麼是不工作 - 這聽起來像正常的請求正在經歷,但會話屬性似乎沒有約束力?

+0

是的,會話屬性綁定不正確。這種方法在Spring 3.0中工作得很好,但它已停止工作。它可能是一個錯誤?傳遞給控制器​​的對象現在似乎是空實例。使用spring-test-mvc方法,我可以像以前一樣傳遞會話對象嗎?如果是這樣,我沒有問題切換。該項目只有2天 - 我還沒有寫很多代碼。在我全速前進之前,我仍然在搞清楚。 – egervari

+0

懷疑它可能是一個bug - Spring MVC代碼在3.0和3.1之間已經發生了很大的變化,處理程序不再是控制器,它實際上是最終的@ RequestMapped方法。你的代碼對於Spring 3.0來說更加不正確,因爲RequestMappingHandlerAdapter只在3.1.0中引入。我假設會話屬性應該正確使用mvc-test - 這裏是一個示例 - https:// github。com/SpringSource/spring-test-mvc/blob/master/src/test/java/org/springframework/test/web/server/samples/standalone/resultmatchers/SessionAttributeAssertionTests.java –

+0

這是關於這個項目的更多信息 - http://rossenstoyanchev.org/blog/2012/06/28/early-milestone-of-spring-test-mvc/ –

0

Here是一個非常好的演示文稿,其中談到了測試彈簧3.1類和控制器,下面是一個例子:

@Test 
public void testSave() { 

    Account account = new Account(); 
    BindingResult result = 
     new BeanPropertyBindingResult(account, "account"); 

    AccountManager mgr = createMock(AccountManager.class); 
    mgr.saveOrUpdate(account); 
    replay(mgr); 

    AccountController contrlr = new AccountController(mgr); 

    String view = contrlr.save(account, result); 

    assertEquals("redirect:accounts", view); 
    verify(mgr); 
} 

希望幫助!

+0

我很清楚,你可以調用控制器的方法像任何其他pojo,但這不會測試映射。所以如果這些映射是錯誤的,那麼它們將不會被測試,直到你在tomcat中試用。除了測試控制器的邏輯之外,我寧願在映射上進行迴歸測試 – egervari

1

這是我在Spring 3.1中使用的測試用例之一。希望它能滿足你的要求。

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml" }) 
public class ControllerTest { 
    @Autowired 
    private RequestMappingHandlerAdapter handleAdapter; 

    @Autowired 
    private RequestMappingHandlerMapping handlerMapping; 
    @Test 
    public void playerControllerTest() throws Exception{ 

     MockHttpServletRequest request = new MockHttpServletRequest(); 
     MockHttpServletResponse response = new MockHttpServletResponse(); 
     request.setRequestURI("/players.show"); 
     request.setMethod("GET"); 

     Object handler = handlerMapping.getHandler(request).getHandler(); 
     ModelAndView mav = handleAdapter.handle(request, response,handler); 

     ModelAndViewAssert.assertViewName(mav,"players"); 

    } 

} 
+0

這實際上與我使用的代碼非常相似。如果您將對象放入會話屬性中,則不起作用。會話將不會正確綁定到該操作。相反,該對象似乎是一個新創建的對象。 – egervari