最近使用SpringMvc寫一個URL比較複雜的RequestMapping,最後使用MockMvc測試下URL。java
出現的問題是根本不存在的URI,竟然返回200。使用如下代碼測試:web
@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration({ "classpath:spring/spring-web.xml" }) public class SearchControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setUp() throws Exception { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } @Test public void testURLMapping() throws Exception { String[] testCase= { "/asdf" // 根本不存在 }; for (String url : testCase) { this.mockMvc.perform(MockMvcRequestBuilders.get(url)) .andDo(MockMvcResultHandlers.print()) // 輸出信息 .andExpect(MockMvcResultMatchers.status().isOk()); } } }
測試經過,可是項目跑起來瀏覽器看HTTP請求返回的是404,輸出的信息以下:spring
MockHttpServletRequest: HTTP Method = GET Request URI = /asdf Parameters = {} Headers = {} Handler: Type = org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200 // 200! Error message = null Headers = {} Content type = null Body = Forwarded URL = default // 問題的關鍵! Redirected URL = null Cookies = []
問題的關鍵就是Forward那裏,這個問題三年前有人反饋過了(https://jira.spring.io/browse/SPR-10695)。瀏覽器
具體緣由:app
內部進行URL匹配未找到會重定向到default setvlet再返回404錯誤,這個重定向是在Tomcat內部完成的,客戶端是察覺不到的。SpringMvc做爲一個servlet能夠看責任鏈模式上的一棒,這個不匹配的請求其實和CSS、Js等靜態文件同樣最後傳遞給了Tomcat的default,最終是Tomcat拋出的404錯誤。MockMvc畢竟不是模擬瀏覽器訪問,MockMvc並不能發現404錯誤,以上是我我的的理解,推薦看一下上面的連接。測試
改進辦法:ui
MockMvc並不知道不匹配的請求最後Tomcat怎樣處理的,可是能夠知道這個請求是在Spring內完成的仍是最後作了重定向。修改爲以下測試代碼:this
this.mockMvc.perform(MockMvcRequestBuilders.get(url)) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(forwardedUrl(null));
完成!url