最近在寫單元測試,遇到一些坑和你們分享一下。
以前咱們一直有service層的單元測試,可是沒有action層的單元測試,正好咱們用到spring mvc,因此就用了spring-test作單元測試,
spring mvc 的單元測試,spring-test是使用mock實現的,提供了 MockHttpServletResponse,MockHttpServletRequest對象,都是經過 javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse 模擬出來的。
一、同步調用
server端controller代碼:
@RequestMapping(value = "/mobile/ios/test", method = RequestMethod.GET)
@ResponseBody
public String test(HttpServletRequest request, final HttpServletResponse response) {
return "sdfsdf";
}
client test 的代碼:
@Test
public void test() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/mobile/ios/test") )
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print()).andReturn();
}
二、異步調用
server端controller代碼:
@RequestMapping(value = "/mobile/ios/testAsyn", method = RequestMethod.GET)
@ResponseBody
public Callable<String> testAsyn(HttpServletRequest request, final HttpServletResponse response) {
return new Callable<String>() {
@Override
public String call() throws Exception {
return "sdfsdf";
}
};
}
client test 的代碼:
@Test
public void testAysn() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get("/mobile/ios/testAsyn").header("X-BlueWare-Connect-Time", 1000 * 30))
.andExpect(MockMvcResultMatchers.request().asyncStarted()).andReturn();
mvcResult.getAsyncResult();
mockMvc.perform(MockMvcRequestBuilders.asyncDispatch(mvcResult)).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn();
}
說一下坑的位置:
一、同步的 controller 用同步的方法測試,好比(get,post,fileUpload,delete),異步的方法用異步測試,好比(Callable ,用asyncDispatch)。這個說不上是否是bug。按正常思惟的話,若是服務端是異步的化,客戶端用異步,同步都是能夠的,這個作的比較怪異。 也是回答Willem Jiang 老師的問題(討論這個是否是bug)。
二、若是用同步的Test 測試異步的服務(Callable)會遇到什麼問題,由於客戶端沒有設置timeToWait,因此根本就沒有等待Callable 的返回值,Test的全部狀態都是正常,就算是在Callable裏拋異常也沒用,也沒有辦法對Callable進行Debug,由於 timeToWait默認爲0,一閃就過去了,這個也是我最開始比較鬱悶的地方。
三、就算是用asyncDispatch,進行也有問題。」.asyncStarted()「一 定要設置,這個是告訴request請求,是異步請求。
四、getAsyncResult()也是一個坑,若是不調用這個方法,asyncDispatch也有問題,由於 timeToWait 默認爲0,直接報錯!這時候你說了,我服務器端有設置呀,<mvc:async-support default-timeout="3000" />
這個選項是配置服務端請求超時的,可是我告訴你,若是沒有調用getAsyncResult()方法,服務端的這個配置是沒有用的。
getAsyncResult(),是一個重載的方法,有一個帶參數的,一個不帶參數的,若是不帶參數,用的是服務端配置 mvc:async-support ,若是帶參數, 則爲客戶端參數的時間(單位毫秒)。java