【springmvc】利用Junit对controller进行单元测试

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

原文地址:https://www.cnblogs.com/hager/p/6874625.html