SpringMVC 測試框架 MockMvc 天坑一枚

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

相關文章
相關標籤/搜索