作者:alanshelby

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

「一、前言」

在前面的章节我们介绍过 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 {@Autowiredprivate WebApplicationContext context;private MockMvc mockMvc;@Beforepublic 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"));
}

img

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

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();
}

img

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

四、小结

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

特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

高手都这么给 Spring MVC 做单元测试!相关推荐

  1. idea junit 测试看不到控制台报错信息_高手都这么给 Spring MVC 做单元测试!

    本章节主要讲解以下两部分内容: 1.Mock 测试简介 2.测试用例演示 一.Mock 测试简介 1.什么是 mock 测试 在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个「虚拟的对象」 ...

  2. Spring mvc 做图片上传

    Spring MVC做图片上传: 一.配置文件中首先配置文件上传路劲: 二.首先获取配置文件路劲当中的路劲并判断路劲是否存在,不存在用File类的mkdirs()创建:(url) 三.获取文件名称(f ...

  3. ssm提交post_我用spring mvc做,用post方式提交,后台获取不到参数值,用get方式就可以,什么问题...

    展开全部 因为form表单e68a843231313335323631343130323136353331333365646330的enctype编码方式不同导致的:enctype 属性规定在发送到服 ...

  4. spring MVC做form提交Neither BindingResult nor plain target object for bean name 'command' available...

    我的改正是在form表单上添加了个modelAttribute="employee"然后在 @RequestMapping(value="/emp",metho ...

  5. 如何用vs做界面_5分钟改完100个界面?高手都在用这个方法做设计!

    工作中大家都可能遇到过,设计完成后因为某些原因突然要批量修改某一个字段文字的大小,或者某个按钮的颜色. 领导一声令下,苦逼的设计师就要累死累活地修改界面了,有时最后的结果可能还是改来改去改回第一版,不 ...

  6. spring mvc+junit

    为什么80%的码农都做不了架构师?>>>    spring mvc的简单单元测试,说白了就是测试spring mvc的controller. 先参考两篇帖子: 1.http://s ...

  7. Spring MVC和Spring Boot的概念以及比较

    Spring MVC是什么? (1)Spring MVC是Spring提供的一个强大而灵活的模块式web框架.通过Dispatcher Servlet, ModelAndView 和 View Res ...

  8. Spring MVC:测试简介

    测试是软件开发中最重要的部分之一. 井井有条的测试有助于使应用程序代码保持良好状态,并且处于工作状态. 有很多不同类型的测试和方法. 在本文中,我想对基于Spring MVC的应用程序进行单元测试进行 ...

  9. 写出我的第一个框架:迷你版Spring MVC

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:张丰哲 https://www.jianshu.com/p/ ...

最新文章

  1. FOPEN FUNCTION
  2. 电子学会 软件编程(图形化)一级训练营
  3. 在JavaScript中遭遇级联表达式陷阱
  4. facebook 文本分类_如何禁用和自定义Facebook的通知,文本和电子邮件
  5. 关于datetime 比较大小失效的问题
  6. (日常搬砖)数据集标注格式转换:txt转xml(VOC格式)
  7. windows电脑记事本怎么自由排序?
  8. java128分解质因数_java分解质因数
  9. 什么是一级域名和二级域名
  10. 【转】敏捷中国十八年目睹之怪现状
  11. Elasticsearch: collapse 去重
  12. 勇敢面对人生的苦难,时光不负赶路人
  13. 台式电脑无法开机,一直显示未检测到信号/显示检测信号线解决方法
  14. ThinkPHP门面源码解析
  15. -XX:MaxDirectMemorySize直接内存无效问题
  16. 前端笔试—编译和体系结构
  17. 柳絮纷飞的日子——CSS笔记之四
  18. Dispatcher has no subscribers for channel排坑指南
  19. 在ROS Kinetic和Gazebo 8中使用智能汽车仿真演示
  20. 阿里云javaweb开发环境搭建(一)(jdk+Tomcat)

热门文章

  1. 谷歌大幅削减其应用商店服务费
  2. 单片机值得学吗?会单片机能找什么工作?
  3. HDU4587(割点+最大连通分量)
  4. 主席树 + 后缀数组求LCP + 二分套二分 ---- P4094 [HEOI2016/TJOI2016]字符串
  5. ILSpy可以反编译c语言,ILSpy反编译工具的使用
  6. closeable java_【转】java.io.Closeable接口
  7. python求圆柱表面积_python基础知识-字典
  8. 算法_棋盘型高维动态规划
  9. html5圆形图片轮播,jQuery超酷响应式圆形图片轮播图特效
  10. java post xmll_HttpClient发送Post请求,内容格式为xml,并获取响应内容