高手都这么给 Spring MVC 做单元测试!

点击上方“码农突围”,马上关注

这里是码农充电第一站,回复“666”,获取一份专属大礼包

真爱,请设置“星标”或点个“在看”

来源:zhuanlan.zhihu.com/p/43260823

  • 一、前言

  • 二、Mock 测试简介

  • 三、测试用例演示

  • 四、小结


一、前言

在前面的章节我们介绍过 Junit 的使用,也了解过 spring-test,今天我们来了解一个新玩意 -- mock 测试。这里仅仅做一个入门,对返回视图和返回 Json 数据的方法进行测试演示,不会把所有的方法都介绍到,具体文档详见链接:Mock Test,本章节主要讲解以下两部分内容:

1、Mock 测试简介

2、测试用例演示

二、Mock 测试简介

1、什么是 mock 测试

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

  • 虚拟的对象就是 mock 对象。

  • mock 对象就是真实对象在调试期间的代替品。

2、为什么使用 mock 测试

  • 避免开发模块之间的耦合

  • 轻量、简单、灵活

3、MockMVC 介绍

基于 RESTful 风格的 SpringMVC 的测试,我们可以测试完整的 Spring MVC 流程,即从 URL 请求到控制器处理,再到视图渲染都可以测试。

1)MockMvcBuilder

MockMvcBuilder 是用来构造 MockMvc 的构造器,其主要有两个实现:StandaloneMockMvcBuilder 和 DefaultMockMvcBuilder,对于我们来说直接使用静态工厂 MockMvcBuilders 创建即可。

2)MockMvcBuilders

负责创建 MockMvcBuilder 对象,有两种创建方式:

standaloneSetup(Object... controllers):通过参数指定一组控制器,这样就不需要从上下文获取了。

webAppContextSetup(WebApplicationContext wac):指定 WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的 MockMvc,本章节下面测试用例均使用这种方式创建 MockMvcBuilder 对象。

3)MockMvc

对于服务器端的 SpringMVC 测试支持主入口点。通过 MockMvcBuilder 构造 MockMvcBuilder 由 MockMvcBuilders 建造者的静态方法去建造。

核心方法:perform(RequestBuilder rb) -- 执行一个 RequestBuilder 请求,会自动执行 SpringMVC 的流程并映射到相应的控制器执行处理,该方法的返回值是一个 ResultActions。

4)ResultActions

(1)andExpect:添加 ResultMatcher 验证规则,验证控制器执行完成后结果是否正确;

(2)andDo:添加 ResultHandler 结果处理器,比如调试时打印结果到控制台;

(3)andReturn:最后返回相应的 MvcResult;然后进行自定义验证 / 进行下一步的异步处理;

5)MockMvcRequestBuilders

用来构建请求的,其主要有两个子类 MockHttpServletRequestBuilder *和 MockMultipartHttpServletRequestBuilder*(如文件上传使用),即用来 Mock 客户端请求需要的所有数据。

6)MockMvcResultMatchers

(1)用来匹配执行完请求后的结果验证

(2)如果匹配失败将抛出相应的异常

(3)包含了很多验证 API 方法

7)MockMvcResultHandlers

(1)结果处理器,表示要对结果做点什么事情

(2)比如此处使用 MockMvcResultHandlers.print() 输出整个响应结果信息

8)MvcResult

(1)单元测试执行结果,可以针对执行结果进行自定义验证逻辑

三、测试用例演示

1、添加依赖

<!-- spring 单元测试组件包 -->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-test</artifactId>
 <version>5.0.7.RELEASE</version>
</dependency>
<!-- 单元测试Junit -->
<dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.12</version>
</dependency>
<!-- Mock测试使用的json-path依赖 -->
<dependency>
 <groupId>com.jayway.jsonpath</groupId>
 <artifactId>json-path</artifactId>
 <version>2.2.0</version>
</dependency>

前两个 jar 依赖我们都已经接触过了,对于返回视图方法的测试这两个 jar 依赖已经足够了,第三个 jar 依赖是用于处理返回 Json 数据方法的,这里要明白每个 jar 的具体作用。

2、被测试的方法

@RequestMapping(value = "editItem")
public String editItem(Integer id, Model model) {
 Item item = itemService.getItemById(id);
 model.addAttribute("item", item);
 return "itemEdit";
}

@RequestMapping(value = "getItem")
@ResponseBody
public Item getItem(Integer id) {
 Item item = itemService.getItemById(id);
 return item;
}

这里我们提供了两个方法,一个是返回视图的方法,另一个是返回 Json 数据的方法,下面我们会给出测试类,分别对这两个方法进行测试。

3、测试类:ItemMockTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/*.xml")
@WebAppConfiguration
public class ItemMockTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @Before
    public void init() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }
}

这里前两个注解就不再解释了,我们在学习 Spring 与 Junit 整合的时候已经讲解过了,这里说一下第三个注解:@WebAppConfiguration:可以在单元测试的时候,不用启动 Servlet 容器,就可以获取一个 Web 应用上下文。

1)返回视图方法测试

@Test
public void test() throws Exception {
 MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/editItem").param("id", "1"))
   .andExpect(MockMvcResultMatchers.view().name("itemEdit"))
   .andExpect(MockMvcResultMatchers.status().isOk())
   .andDo(MockMvcResultHandlers.print())
   .andReturn();
 Assert.assertNotNull(result.getModelAndView().getModel().get("item"));
}

这三句代码是我们对结果的期望,最后打印出了结果,说明执行成功,所有期望都达到了,否则会直接报错。从结果中我们就可以看到这个请求测试的情况。

2、返回 Json 数据方法

@Test
public void test1() throws Exception {
 mockMvc.perform(MockMvcRequestBuilders.get("/getItem")
   .param("id", "1")
   .accept(MediaType.APPLICATION_JSON))
   .andExpect(MockMvcResultMatchers.status().isOk())
   .andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
   .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1))
   .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("IPhone X"))
   .andDo(MockMvcResultHandlers.print())
   .andReturn();
}

在这个方法中比较特殊的就是设置 MediaType 类型,因为都是使用 Json 格式,所以设置了 MediaType.APPLICATION_JSON,jsonPath 用于比对期望的数据是否与返回的结果一致,这里需要注意的是 "$.id" 这 key 的种形式。

四、小结

这里只是用到了 MockMvc 很小一部分知识,更加深入学习会使你养成一种良好编写单元测试的习惯,这是十分难得的一种好习惯,推荐去看官方文档,然后动手去测试一下,为你编写的每一个 Controller 方法进行测试,保证他们的可靠性。

最近有有不少老铁在后台留言说,想进大厂,但是算法不好。最近我整理了一份刷题实录,这份刷题实录,也让我进了心仪的大厂。现在开放分享给大家。希望对大家有所帮助。
任何的算法题,如同写作文一样,都有一些模板可以套用的。比如面试常考的DP(动态规划),难的是一些关键点是否能想清楚。比如你能写出动态转移方程,这题基本上就可以AC了。整个刷题实录内容,包括 双子针、动态规划、二分查找、贪心算法、深度优先搜索、字符串、递归、字典树、排序、链表等相关专题内容。图文并茂,附有刷题答案源码。
刷题任务的题目,是根据题目的类型来汇总的,总结了八个类别,每个类别下面也总结了5个左右的题型,帮助大家分门别类的突破,所以刷起来相对会更有重点和针对性。如果从头到尾的刷,每周按顺序刷42题,很容易让自己坚持不下来,也会觉得很枯燥。所以在制定计划的时候可以让这个计划变得更“有趣"和针对性,让它看起来更容易实现一点,才会更容易坚持。
目前上述内容已打包成完整电子书,具体获取方式如下:扫描关注 Github爱好者社区 公众号;在 Github爱好者社区 公众号后台回复关键词「9999」获取下载地址。扫描关注,回复"9999"即可下载
最近热文•  为什么我强烈建议大家使用 Linux 开发?•  保送北大,连发三篇Science,这位80后川妹子近日再发重磅级研究成果!•  如何一眼就分辨出本科、硕士和博士?•  记录下入职中软一个月(外包华为),就离职了!

最近整理了一份大厂算法刷题指南,包括一些刷题技巧,在知乎上已经有上万赞。同时还整理了一份6000页面试笔记。关注下面公众号,在公众号内回复「刷题」,即可免费获取!回复「加群」,可以邀请你加入读者群!

明天见(。・ω・。)ノ♡
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值