最近使用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