之前已經對Service層進行了mock和Junit結合的單側了。今天搞了一下對controller層的單側;
網上找了半天,怎么寫的都有(當然,也許人家場景就那樣);后來,我這個Java新手也比葫蘆畫瓢來搞了一個:
@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(locations = { "classpath:spring-include.xml" // 這里加載你用到的配置xml文件就可以了,可以配置多個 }) public class MediaControllerTest { private MockMvc mockMvc; @Mock private MediaService mediaService; @InjectMocks MediaController mediaController; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); this.mockMvc = MockMvcBuilders.standaloneSetup(mediaController).build(); } @After public void tearDown() throws Exception { } @Test public void index() throws Exception { // 構造一個查詢條件 MediaSearchModel mediaSearchModel = new MediaSearchModel(); mediaSearchModel.setBeginTime("2016-05-18"); mediaSearchModel.setEndTime("2017-05-18"); // String json = JsonHelper.serialize(mediaSearchModel); // mock一個返回值 List<AdvertiserAndMediaStatViewModel> mockResult = new Page<>(); AdvertiserAndMediaStatViewModel mockModel = new AdvertiserAndMediaStatViewModel(); mockModel.setTask_count(999L); mockResult.add(mockModel); // mock 方法返回值 when(mediaService.getAdvertiserAndMediaStatList(mediaSearchModel)).thenReturn(mockResult); // 模擬一個post請求,把參數傳遞進去 this.mockMvc.perform( ( post("/media/adv-media-stat-list-pager") .contentType(MediaType.APPLICATION_JSON) .param("start", "0") .param("length", "10") .flashAttr("searchModel", mediaSearchModel)// 在這里踩坑了,見下面描述
) ).andExpect(status().isOk()).andDo(print());
// 驗證方法是否被調用1次;
verify(mediaService, times(1)).getAdvertiserAndMediaStatList(mediaSearchModel); }
}
MediaController中的方法定義為:
@ResponseBody @RequestMapping(value = "adv-media-stat-list-pager", method = RequestMethod.POST) public Protocol advertiserAndMediaStatList(@ModelAttribute("searchModel") MediaSearchModel searchModel, Integer start, Integer length) { // 實現邏輯 }
輸出結果:
MockHttpServletRequest: HTTP Method = POST Request URI = /media/adv-media-stat-list-pager Parameters = {start=[0], length=[10]} Headers = {Content-Type=[application/json]} Handler: Type = com.xxx.web.controller.media.MediaController Method =......... 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 Error message = null Headers = {Content-Type=[application/json;charset=UTF-8]} Content type = application/json;charset=UTF-8 Body = {"returncode":0,"message":"成功","result":{"rowcount":0,"pagecount":0,"pageindex":0,"list":[{"task_count":999}]}} Forwarded URL = null Redirected URL = null Cookies = []
Q&A:
Q、.flashAttr("searchModel", mediaSearchModel)// 在這里踩坑了,見下面描述
A、在給方法傳遞被標注為@ModelAttribute的參數時,需要給ModelAttribute指定一個名稱;否則傳不過去參數;可以參考http://stackoverflow.com/questions/6339777/set-modelattribute-in-mockhttpservletrequest-in-junit-test
參考:
Mock、InjectMock :http://site.mockito.org/
http://www.cnblogs.com/wade-xu/p/4311657.html
http://stackoverflow.com/questions/6339777/set-modelattribute-in-mockhttpservletrequest-in-junit-test