Mockito以及MockMVC的使用
开始实习了,公司布置的第一个任务就是写Mock单元测试,学了一个礼拜,稍微写写心得体会,记录一下。
mockito启动很简单,通常配合junit 4使用
先导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
Mockito框架中有几种启动的方式
最常见的就是第三种在测试类上加一个注解的方式
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Before
public void init(){
MockitoAnnotations.initMocks(this);
}
@RunWith(MockitoJUnitRunner.class)
public class MockByRunnerTest {
}
Mock 注入:模拟一个虚假的对象,执行虚拟的方法,规定好返回参数
InjectMock注入:调用的是真实的方法
一般就是执行真实的方法过程中调用虚拟的Mock注入来仅仅执行当前层的逻辑
比如你想检查控制层Controller层的逻辑
可以注入Mapper层和Service层的对象,然后用Controller层调用真实方法
我们有如下Controller层,想要检查listJson方法
@RequestMapping("listJson")
@ResponseBody
public PageResult<CourseOrder> listJson(CourseOrder condition, int page, int limit) {
//这里有service,因此后面要mock
PageResult<CourseOrder> result = courseOrderService.findPageResult(condition, page, limit);
return result;
}
对应测Test这样写
@Mock
private CourseOrderService courseOrderService;
@InjectMocks
private CourseOrderController courseOrderController;
@Test
public void listJson() {
//定义假数据
CourseOrder condition = new CourseOrder();
//规定一下规则,进行打桩
when(courseOrderService.findPageResult(condition, anyInt(), anyInt())).thenReturn(null);
//真实方法调用
PageResult<CourseOrder> result = courseOrderController.listJson(null, 1, 33);
//检查一下
assertThat(result, equalTo(null));
}
注意,这样做并不能检查Service层的findPageResult方法
如果想要检查该方法,那我们可以对Service层做Mock
先展示一下Service层代码
@Override
public PageResult<CourseOrder> findPageResult(CourseOrder condition, int page, int pageSize) {
PageResult<CourseOrder> result = new PageResult<>();
result.setCode(0);
Map<String, Object> params = new HashMap<>();
params.put("condition", condition);
params.put("start", (page - 1) * pageSize);
params.put("pageSize", pageSize);
//这里Service层调用了mapper层中的方法,正是我们需要Mock的地方
int total = courseOrderMapper.findCountByMap(params);
result.setCount(total);
//同前
List<CourseOrder> list = courseOrderMapper.findOrderByMap(params);
result.setData(list);
return result;
}
Service中findPageResult方法对应的test
@Mock
private CourseOrderMapper courseOrderMapper;
@InjectMocks
private CourseOrderService courseOrderService;
@Test
public void findPageResult() {
Map<String, Object> params = new HashMap<>();
List<CourseOrder>list = new ArrayList<>();
when(courseOrderMapper.findCountByMap(params)).thenReturn(1);
when(courseOrderMapper.findOrderByMap(params)).thenReturn(list);
//这里参数随便写因为用不到
PageResult<CourseOrder> pageResult = courseOrderService.findPageResult(null, 1, 1);
System.out.println(pageResult);
}
如果我们要去达到postman那样的功能
我们可以使用MockMVC工具,它是对于接口进行Mock,模拟Web环境
//这是老版本的导入,针对springBoot 1.4之前的版本
//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:resource下xml或者yml格式的配置文件")
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
public class CourseOrderControllerWebTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setup(){
//首先要进行初始化
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void save() throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders
.post("/courseOrder/save"); //验证接口url
.accept(MediaType.APPLICATION_JSON)) //accept指定客户端能够接收的内容类型
//.param()可以规定发送具体参数
//但是假如需要发送Json格式形式的数据,也就是被ResponseBody修饰需要以下做法
//可能会报400,先使用com.alibaba.fastjson.JSONObject将对象转换为Json数据
String requestJson = JSONObject.toJSONString(folderInfo);
//然后用.contentType()规定服务器传送的数据是什么格式
.contentType(MediaType.APPLICATION_JSON).content(requestJson))
//看看是否返回正确的状态码
MvcResult mvcResult = mockMvc.perform(builder)
.andDo(MockMvcResultHandlers.print())
//等同于Assert.assertEquals(200,status);
.andExpect(MockMvcResultMatchers.status().is2xxSuccessful())
.andReturn();
//打印返回结果
System.out.println(mvcResult.getResponse().getContentAsString());
}
}
返回结果截图