之前已经对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