MockMvc 基础使用

苏友朋

发布于 2018.10.15 12:10 阅读 3277 评论 0

前言:

昨日同事展示了MockMvc的基本用法,我发现它有可能会给我后面的工作带来极大的便利,因此今天对它的简单使用进行了研究,研究结果记录如下,以便日后使用。

 

 

什么是mock测试:

mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

 

为什么使用mock测试:

我们现在只能使用junit测试service层以下的代码,想要测试controller层,要么等待前段页面及代码等编辑完成后统一测试,要么使用postman测试(特别是post方法,因为get方法可以通过在浏览器地址栏中输入地址进行测试)。

上述两种方式都有一步无法绕开的过程:开启web服务器(开启tomcat)。特别是在只进行了少量修改,却需要多次修改多次测试的情境下,这种方法极不方便。

使用MockMvc就可以像测试普通service层那样测试controller层(虽然由于有时候需要读取配置文件,导致测试过程较慢,但是仍比传统方式方便快捷许多)。

 

使用:

一. maven依赖要求:

  1. Junit必须在4.9版本以上
  2. spring版本必须在3.2以上
  3. 使用的框架必须是springMvc框架

 二. maven依赖添加

<dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-test</artifactId>  
    <version>${spring.version}</version>  
    <scope>test</scope>  
</dependency>  

三. 被测试类及测试类

测试方式一:被测试类中不存在mybatis逻辑时

被测试类:

package com.lindasoft.controller;
import 略
@Slf4j
@Controller
@RequestMapping("/dayOff")
@SuppressWarnings("SpringJavaAutowiringInspection")//抑制idea对spring对注入的service不识别的报错
public class DayOffController {
    @Resource
private DayOffService dayOffService;

    @RequestMapping(value = "/getAllDayOff", method = RequestMethod.POST)
    @ResponseBody
    public JsonResult getAllDayOff(@RequestParam Integer ceshi,@ModelAttribute DayOff dayOff) {
        JsonResult jsonResult = new JsonResult();
        System.out.println("ceshi:"+ceshi);
        System.out.println("dayoff:"+dayOff.getClassesName());
        List<DayOff> dayOffs = new ArrayList<>();
        if(dayOffs.size()>0){
            jsonResult.setSuccess(true);
            jsonResult.setRoot(dayOffs);
        }else {
            jsonResult.setSuccess(true);
            jsonResult.setFailReason("请假信息获取失败");
        }
        return jsonResult;
    }
}

测试类:

package com.lindasoft.controller;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;


public class DayOffControllerTest {

    private MockMvc mockMvc;
    private DayOffController dayOffController;

    @Before
    public void setUp() throws Exception {
        dayOffController = new DayOffController();
        mockMvc = MockMvcBuilders.standaloneSetup(dayOffController).build();
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void getAllDayOff() {
        try {
            MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders
                    .post("/dayOff/getAllDayOff")
                    .param("ceshi", "10")
                    .param("classesName", "su");
            MvcResult result = mockMvc.perform(mockHttpServletRequestBuilder)
                    //.andExpect(MockMvcResultMatchers.view().name("dayOff/getAllDayOff"))//暂时没有探索出用途
                    //.andDo(MockMvcResultHandlers.print())//将输出完整信息
                    .andReturn();
            int status = result.getResponse().getStatus();
            System.out.println("请求状态码:" + status);
            String resultstr = result.getResponse().getContentAsString();
            System.out.println("接口返回结果:" + resultstr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
测试方式二:被测试类中存在mybatis逻辑时

被测试类:

package com.lindasoft.controller;
import 略
@Slf4j
@Controller
@RequestMapping("/dayOff")
@SuppressWarnings("SpringJavaAutowiringInspection")//抑制idea对spring对注入的service不识别的报错
public class DayOffController {
    @Resource
private DayOffService dayOffService;

    @RequestMapping(value = "/getAllDayOff", method = RequestMethod.POST)
    @ResponseBody
    public JsonResult getAllDayOff(@RequestParam Integer ceshi,@ModelAttribute DayOff dayOff) {
        JsonResult jsonResult = new JsonResult();
        System.out.println("ceshi:"+ceshi);
        System.out.println("dayoff:"+dayOff.getClassesName());
        List<DayOff> dayOffs = dayOffService.getAllDayOff();
        if(dayOffs.size()>0){
            jsonResult.setSuccess(true);
            jsonResult.setRoot(dayOffs);
        }else {
            jsonResult.setSuccess(true);
            jsonResult.setFailReason("请假信息获取失败");
        }
        return jsonResult;
    }
}

测试类:由于被测试类中使用了@ Resource注解的接口,因此需要调用springMVC+mybatis的配置文件

package com.lindasoft.controller;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;


public class DayOffControllerTest {

    private MockMvc mockMvc;
    private ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
    private DayOffController dayOffController;

    @Before
    public void setUp() throws Exception {
        dayOffController = applicationContext.getBean(DayOffController.class);
        mockMvc = MockMvcBuilders.standaloneSetup(dayOffController).build();
        //extGroupMapper = applicationContext.getBean(ExtGroupMapper.class);

    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void getAllDayOff() {
        try {
            MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders
                    .post("/dayOff/getAllDayOff")
                    .param("ceshi", "10")
                    .param("classesName", "su");
            MvcResult result = mockMvc.perform(mockHttpServletRequestBuilder)
                    //.andExpect(MockMvcResultMatchers.view().name("dayOff/getAllDayOff"))//暂时没有探索出用途
                    //.andDo(MockMvcResultHandlers.print())//将输出完整信息
                    .andReturn();
            int status = result.getResponse().getStatus();
            System.out.println("请求状态码:" + status);
            String resultstr = result.getResponse().getContentAsString();
            System.out.println("接口返回结果:" + resultstr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
测试方式三:被测试类中存在@RequestBody标签时

被测试类:

    @RequestMapping(value = "/updateMenu", method = RequestMethod.POST)
    @ResponseBody
    public JsonResult updateMenu(
            @RequestParam(required = false, defaultValue = "10") Integer limit,
            @RequestBody List<Menu> permissionList,
            HttpSession session) {


        return frequentlyMenuService.updateMenu(permissionList,session);
    }

自定义Menu类:

@Data
public class Menu {
    private Long id;

    private String name;

}

测试类:

@Test
    public void updateMenu() {
        try {
            List<Menu> list = new ArrayList<>();
            Menu m = new Menu;
            m.setId(1);
            m.setName("sss");
            Menu m1 = new Menu;
            m1.setId(1);
            m1.setName("sss");
            list.add(m);
            list.add(m1);
            String paramStr = JSONObject.toJSONString(list);
            System.out.println(paramStr);
            MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders
                    .post(url+"/updateMenu")
                    .contentType(MediaType.APPLICATION_JSON).content(paramStr)
                    //.param("permissionList", "%5b1%2c2%2c3%5d")
                    .param("limit", "5");
            MvcResult result = mockMvc.perform(mockHttpServletRequestBuilder)
                    //.andExpect(MockMvcResultMatchers.view().name("dayOff/getAllDayOff"))//暂时没有探索出用途
                    .andDo(MockMvcResultHandlers.print())//将输出完整信息
                    .andReturn();
            int status = result.getResponse().getStatus();
            System.out.println("请求状态码:" + status);
            String resultstr = result.getResponse().getContentAsString();
            System.out.println("接口返回结果:" + resultstr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }