您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
通过MockMVC实现REST接口单测化的测试
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
通过MockMVC实现REST接口单测化的测试
自猿其说Tech
2022-07-14
IP归属:未知
288400浏览
测试
### 1 MockMvc是什么? MockMvc是由spring-test包提供,实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,使得测试速度快、不依赖网络环境。同时提供了一套验证的工具,结果的验证十分方便。 接口MockMvcBuilder,提供一个唯一的build方法,用来构造MockMvc。主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,分别对应两种测试方式,即独立安装和集成Web环境测试(并不会集成真正的web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)。 MockMvcBuilders提供了对应的创建方法standaloneSetup方法和webAppContextSetup方法,在使用时直接调用即可。 ### 2 MockMVC如何使用? #### 2.1 springBoot中使用 1)在springBoot项目中可能需要引入的maven pom配置为 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> ``` 2)创建HelloWorldController类,并提供hello方法作为待测试的业务接口 ```java @RestController public class HelloWorldController { @RequestMapping public String hello(String name){ return "Hello " + name + "!"; } } ``` 3)编写测试类,实例化MockMvc有两种形式,一种是使用StandaloneMockMvcBuilder,另外一种是使用DefaultMockMvcBuilder。 ``` @RunWith(SpringRunner.class) //SpringBoot1.4版本之前用的是@SpringApplicationConfiguration(classes = Application.class) @SpringBootTest //测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的 @WebAppConfiguration public class HelloWorldTest { private MockMvc mockMvc; @Autowired private WebApplicationContext webApplicationContext; @Before public void setup() { // 实例化方式一 mockMvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); // 实例化方式二 //mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } } ``` 4)编写测试方法 ``` @Test public void testHello() throws Exception { /* * 1、mockMvc.perform执行一个请求。 * 2、MockMvcRequestBuilders.get("XXX")构造一个请求。 * 3、ResultActions.param添加请求传值 * 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型 * 5、ResultActions.andExpect添加执行完成后的断言。 * 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情 * 比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。 * 7、ResultActions.andReturn表示执行完成后返回相应的结果。 */ mockMvc.perform(MockMvcRequestBuilders .get("/hello") // 设置返回值类型为utf-8,否则默认为ISO-8859-1 .accept(MediaType.APPLICATION_JSON_UTF8_VALUE) .param("name", "Tom")) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content().string("Hello Tom!")) .andDo(MockMvcResultHandlers.print()); } ``` #### 2.2 springMVC中使用 在springMVC项目中可能需要引入的maven pom配置为 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>1.4.7.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.5.RELEASE</version> <scope>test</scope> </dependency> ``` 2)编写测试用例基本与springBoot一致 #### 2.3 mockMvc初始化方法 1)MockMvcBuilders.standaloneSetup,在standaloneSetup中写入待测试的control ``` mockMvc = MockMvcBuilders.standaloneSetup(templateController).build(); mockMvc = MockMvcBuilders.standaloneSetup(TemplateController.class).build(); ``` 2)MockMvcBuilders.webAppContextSetup,创建默认的mockMVC ``` mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); ``` 这种默认是找不到control的,需要指定查找的路径,可以通过@ComponentScan配置扫描路径 ``` @ComponentScan(basePackages = "com.secbro2") ``` 或者通过MockMvcRequestBuilders的post或者get方法中加入测试的control class ``` RequestBuilder requestBuilder = MockMvcRequestBuilders .post("/jimcache/set",JimCacheRESTControl.class) .accept(MediaType.APPLICATION_JSON_VALUE).content(JSON.toJSONString(bean)) .contentType(MediaType.APPLICATION_JSON_VALUE); ``` ### 3 MockMvc三种常用接口测试 #### 3.1 get方法 ``` mockMvc.perform(MockMvcRequestBuilders .get("/hello") // 设置返回值类型为utf-8,否则默认为ISO-8859-1 .accept(MediaType.APPLICATION_JSON_UTF8_VALUE) .param("name", "Tom")) ``` get方法入参通过param传入,如果是个list则对应的写入多个值就好,accept表示返回的报文类型 #### 3.2 post formdata方法 ``` String JSON = ""; MockHttpServletResponse response = mockMvc.perform(MockMvcRequestBuilders .post("/tfcController/clearOfcCache.json", TfcOrderController.class) .contentType(MediaType.APPLICATION_FORM_URLENCODED) .accept(MediaType.APPLICATION_FORM_URLENCODED) .param("dataJson",JSON)) .andDo(MockMvcResultHandlers.print()) .andReturn() .getResponse(); ``` post表单方法通过param方法传值,accept表示返回报文的格式,contentType表示入参格式 #### 3.3 post json方法 ``` JimCacheBean bean =new JimCacheBean(); bean.setJimUrl("jim://2581598003362223711/80000008"); bean.setCfsLocalIP("192.168.171.31"); bean.setRedisLocalIP("10.170.220.254"); bean.setKey("123-test"); bean.setValue("test-123"); System.out.println(JSON.toJSONString(bean)); mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/jimcache/set",JimCacheRESTControl.class) .accept(MediaType.APPLICATION_JSON_VALUE).content(JSON.toJSONString(bean)) .contentType(MediaType.APPLICATION_JSON_VALUE); MockHttpServletResponse response = mockMvc.perform(requestBuilder) .andReturn() .getResponse(); ``` post json方法通过content方法传值,accept表示返回报文的格式,contentType表示入参格式 ### 4 应用案例 在Promise的web页面中有一个重ofc拉取订单的一个页面,其中如果传入云仓的话,后台需要重新查找云仓对应的配送中心,然后再去ofc拉取订单(遗憾的是这段处理的逻辑没有日志,测试环境与ofc的配置也不通,无法通过日志在测试环境验证)。 ![](//img1.jcloudcs.com/developer.jdcloud.com/33b5fa74-57c1-4244-b221-aba5703b0e7820220714135050.png) 通过MockMvc测试启动,debug进入处理逻辑与服务启动进入debug调试的功效基本相同,但是mockMvc不用真正将服务启动起来就可以访问接口相对轻量级。 相对于CR来说有真实数据正式验证。相对于起本地服务来说省去了起服务的烦恼。同时还能作为自动化持久化保存下来。 相对于普通的单测来说,MockMvc是从入口开始测试,更加的能还原用户的使用场景。 ### 5 常见问题 1. mockmvc返回404Error,一般是默认的mockMvc找不到control导致的,可能是url错误或未指定control 2. mockmvc返回415错误,可能原因是mockMvc的request构建的accept和contentType与定义要求不一致,如果全部正确仍然是415,则从spring加载的角度去排查,可能是mvc项目启动没加载mvc框架,导致接口传任何值都校验不过 3. control中引入的bean无法自动加载问题解决,将control当作一个bean写入到xml中注入,则可解决 ------------ ###### 自猿其说Tech-JDL京东物流技术与数据智能部 ###### 作者:徐桂贵
原创文章,需联系作者,授权转载
上一篇:国际计费系统基于Sharding-Proxy大数据迁移方案实践
下一篇:Opencv系列之一:简介与基本使用
相关文章
安全测试之探索windows游戏扫雷
Jmeter压测实战:Jmeter二次开发之JSF采样器实现
Laputa自动化测试框架介绍
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号