说明
往常 ,我们junit测试一般都针对service层,现在越来越多直接基于控制层做单元测试了,因为控制层对业务场影测试更具代表性,更能有效的进行排错
如何配置?
如何Mock各种控制层接口请求(带附件上传接口)?
如何校验结果?
好了,话不多说,先上一段demo
依赖配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
demo控制器
/**
* @author hushowly
* @date 2020年6月4日 下午4:59:42
*/
@RestController
@RequestMapping("/demo")
public class DemoController {
@GetMapping("/listDemo")
@ResponseBody
public ResultVo<List<Integer>> listDemo(String p1, Integer p2) {
//return ResultVo.oK(Arrays.asList(1,2,3,5));
return ResultVo.error(Arrays.asList(1,2,3,5));
}
}
控制器单元测试
/**
* DemoControllerTest
*
* @author hushow
* @date 2020年6月4日 下午5:03:29
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestDemoApplication.class)
public class DemoControllerTest {
@Autowired
private WebApplicationContext wac;
public MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void getTest() throws Exception {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("examId", "10");
queryParams.add("status", "哈哈哈");
mockMvc
.perform(MockMvcRequestBuilders.get("/demo/listDemo").contentType(MediaType.APPLICATION_JSON)
.characterEncoding(StandardCharsets.UTF_8.name()).accept(MediaType.APPLICATION_JSON)
.characterEncoding(StandardCharsets.UTF_8.name()).queryParams(queryParams))
.andExpect(MockMvcResultMatchers.status().isOk())
// 将响应json转换为对象,校验结果
.andExpect(result -> assertTrue("hasOK",
JSONObject.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8),
new TypeReference<ResultVo<?>>() {}).hasOK()))
// 打印结果和返回结果
.andDo(MockMvcResultHandlers.print()).andReturn();
}
}
Mock各种请求
主要是基于MockMvcRequestBuilders构造类,来模拟http相关参参数配置,以下对几种常用控制器接口mock进行介绍
注:请求响应contentType及characterEncoding
get url 带参
MockMvcRequestBuilders.get("/demo/listDemo").contentType(MediaType.APPLICATION_JSON)
.characterEncoding(StandardCharsets.UTF_8.name()).accept(MediaType.APPLICATION_JSON)
.queryParams(queryParams);
post url&body 带参
MockMvcRequestBuilders.post("/demo/listDemo2").contentType(MediaType.APPLICATION_JSON)
.characterEncoding(StandardCharsets.UTF_8.name()).accept(MediaType.APPLICATION_JSON)
.queryParams(queryParams)
.content(jsonStr);
post 附件&url 带参
@Test
public void attachementTest() throws Exception {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("p1", "10");
queryParams.add("p2", "1");
//测试附件应放入src/test/resources目录下
String fileUrl = "classpath:com/hushow/demo/cj.xlsx";
byte[] fileByte = FileCopyUtils.copyToByteArray(ResourceUtils.getFile(fileUrl));
MockMultipartFile file = new MockMultipartFile("myfile", "cj.xlsx", null, fileByte) ;
mockMvc.perform(MockMvcRequestBuilders.multipart("/demo/attachmentTest").file(file)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.characterEncoding(StandardCharsets.UTF_8.name())
.accept(MediaType.APPLICATION_JSON)
.queryParams(queryParams))
.andExpect(MockMvcResultMatchers.status().isOk())
// 将响应json转换为对象,校验结果
.andExpect(result -> assertTrue("hasOK",
JSONObject.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8),
new TypeReference<ResultVo<?>>() {}).hasOK()))
.andDo(MockMvcResultHandlers.print())
// 打印结果和返回结果
.andDo(MockMvcResultHandlers.print()).andReturn();
}
校验结果
主要是通过MockMvcResultMatchers构造类,创建各种已封装好的校验工具以下针对几种常用校验方式进行说明
http状态校验
.andExpect(MockMvcResultMatchers.status().isOk())
JsonPath 校验
jsonpath语法参考JsonPath是GitHub上的一个开源项目,主要用来对Json格式的数据进行一些处理
//判断值
.andExpect(MockMvcResultMatchers.jsonPath("$['code']").value(1))
//判断元素个数
.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(3));
fastjson全结果反序列化校验
全结果反序列化再进行断方,推荐使用上述方式,速度更快
.andExpect(result -> assertTrue("hasOK", JSONObject.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), new TypeReference<ResultVo<?>>() {}).hasOK()))