引入MockMVC进行单元测试,可以省去很多麻烦
Posted 测试baby
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了引入MockMVC进行单元测试,可以省去很多麻烦相关的知识,希望对你有一定的参考价值。
对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立HTTP Client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,这样会导致测试无法进行,为了可以对Controller进行测试,可以通过引入MockMVC进行解决。
MockMVC实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
MockMVCBuilder是用来构造MockMVC的构造器,其主要有两个实现:StandaloneMockMVCBuilder和DefaultMockMVCBuilder,分别对应两种测试方式,即独立安装和集成Web环境测试(此种方式并不会集成真正的Web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)。对于我们来说直接使用静态工厂MockMVCBuilders创建即可。
下面就写一个简单的案例,告诉你是如何使用MockMVC进行Controller测试的。
创建一个Maven项目(springboot-junit),并配置pom.xml,参照下面代码:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.lvgang</groupId>
<artifactId>springboot-junit</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-junit</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>
创建一个Controller类,我们在后面就测试空上Controller
package org.lvgang;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/")
public String hello(String name){
return "hello "+name;
}
}
下面我们就是编写测试类了:
package org.lvgang;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
//SpringBoot1.4版本之前用的是SpringJUnit4ClassRunner.class
@RunWith(SpringRunner.class)
//SpringBoot1.4版本之前用的是@SpringApplicationConfiguration(classes = Application.class)
@SpringBootTest(classes = App.class)
//测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的
@WebAppConfiguration
public class HelloControllerTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception{
//MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc;
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
}
@Test
public void getHello() 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()输出整个响应结果信息。
* 5、ResultActions.andReturn表示执行完成后返回相应的结果。
*/
MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/")
.param("name","lvgang")
.accept(MediaType.TEXT_HTML_VALUE))
// .andExpect(MockMvcResultMatchers.status().isOk()) //等同于Assert.assertEquals(200,status);
// .andExpect(MockMvcResultMatchers.content().string("hello lvgang")) //等同于 Assert.assertEquals("hello lvgang",content);
.andDo(MockMvcResultHandlers.print())
.andReturn();
int status=mvcResult.getResponse().getStatus(); //得到返回代码
String content=mvcResult.getResponse().getContentAsString(); //得到返回结果
Assert.assertEquals(200,status); //断言,判断返回代码是否正确
Assert.assertEquals("hello lvgang",content); //断言,判断返回的值是否正确
}
}
整个测试过程如下:
1、准备测试环境
2、通过MockMvc执行请求
3、添加验证断言
4、添加结果处理器
5、得到MvcResult进行自定义断言/进行下一步的异步请求
6、卸载测试环境
通过执行HelloControllerTest,得到以下结果:
并且把整个返回结果都打印到了Console中
MockHttpServletRequest:
HTTP Method = GET
Request URI = /
Parameters = {name=[lvgang]}
Headers = {Accept=[text/html]}
Handler:
Type = org.lvgang.HelloController
Method = public java.lang.String org.lvgang.HelloController.hello(java.lang.String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/html;charset=UTF-8], Content-Length=[12]}
Content type = text/html;charset=UTF-8
Body = hello lvgang
Forwarded URL = null
Redirected URL = null
Cookies = []
通过以上代码,我们就完成了一个简单的案例。
这里给大家整理了一份《软件测试工程师进阶的技术栈》,包含了诸多技术栈,希望能帮助在升级打怪中提供中坚力量
给大家推荐下我自己建的软件测试交流学习群: 902061117 ,群里都是搞软件测试的,如果你正在学习测试 ,小编欢迎你加入,大家都是测试党,群内不定期分享干货(都是软件测试相关的),包括我自己整理的一份2021最新的进阶自动化资料。
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你
关注我的微信公众号【伤心的辣条】免费获取~
送上一句话:
世界的模样取决于你凝视它的目光,自己的价值取决于你的追求和心态,一切美好的愿望,不在等待中拥有,而是在奋斗中争取。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!
好文推荐:
以上是关于引入MockMVC进行单元测试,可以省去很多麻烦的主要内容,如果未能解决你的问题,请参考以下文章
Spring 的 MockMvc 是用于单元测试还是集成测试?
单元测试 - 使用 MockMvc 使用 @RequestHeader 和 HashMap 测试控制器
org.springframework.web.util.NestedServletException : 单元测试中的 MockMVC 请求处理失败