SpringBoot使用MockMVC单元测试Controller
对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如启动速度慢,测试验证不方便,依赖网络环境等,这样会导致测试无法进行,为了可以对Controller进行测试,可以通过引入MockMVC进行解决。
MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
MockMvcBuilder是用来构造MockMvc的构造器,其主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,分别对应两种测试方式,即独立安装和集成Web环境测试(此种方式并不会集成真正的web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)。对于我们来说直接使用静态工厂MockMvcBuilders创建即可。
下面就写一个简单的案例,告诉你是如何使用MockMvc进行Controller测试的
01 创建项目
创建一个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\"> -
4.0.0 -
org.lvgang -
springboot-junit -
1.0-SNAPSHOT -
jar -
springboot-junit -
http://maven.apache.org -
-
org.springframework.boot -
spring-boot-starter-parent -
2.1.3.RELEASE -
-
-
UTF-8 -
-
-
-
org.springframework.boot -
spring-boot-starter-web -
-
-
org.springframework.boot -
spring-boot-starter-test -
-
-
创建一个Controller类,我们在后面就测试空上Controller

02 编写测试类
下面我们就是编写测试类了:
-
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); //断言,判断返回的值是否正确 -
} -
}
整个测试过程如下:
-
准备测试环境
-
通过MockMvc执行请求
-
添加验证断言
-
添加结果处理器
-
得到MvcResult进行自定义断言/进行下一步的异步请求
-
卸载测试环境
03 测试结果
通过执行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 = []
通过以上代码,我们就完成了一个简单的案例。
附:
RequestBuilder/MockMvcRequestBuilders:
在上面的测试类中,我们用到了这么一个类MockMvcRequestBuilders用来构建请求的,此类有以下主要的API:
-
MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的MockHttpServletRequestBuilder;如get(/user/{id}, 1L); -
MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables):同get类似,但是是POST方法; -
MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables):同get类似,但是是PUT方法; -
MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) :同get类似,但是是DELETE方法; -
MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables):同get类似,但是是OPTIONS方法; -
MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables):提供自己的Http请求方法及uri模板和uri变量,如上API都是委托给这个API; -
MockMultipartHttpServletRequestBuilderfile Upload(String urlTemplate, Object... urlVariables):提供文件上传方式的请求,得到MockMultipartHttpServletRequestBuilder; -
RequestBuilder asyncDispatch(final MvcResult mvcResult):创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder;
MockMvcRequestBuilders通过方法得到两类Builder:
-
一个是MockHttpServletRequestBuilder
-
一个是MockMultipartHttpServletRequestBuilder (上传文件)
MockHttpServletRequestBuilder:
主要有以下API:
-
MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders):添加头信息; -
MockHttpServletRequestBuilder contentType(MediaType mediaType):指定请求的contentType头信息; -
MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes):指定请求的Accept头信息; -
MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content):指定请求Body体内容; -
MockHttpServletRequestBuilder param(String name,String... values):请求传入参数 -
MockHttpServletRequestBuilder cookie(Cookie... cookies):指定请求的Cookie; -
MockHttpServletRequestBuilder locale(Locale locale):指定请求的Locale; -
MockHttpServletRequestBuildercharacterEncoding(String encoding):指定请求字符编码; -
MockHttpServletRequestBuilder requestAttr(String name, Object value) :设置请求属性数据; -
MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map sessionAttributes):设置请求session属性数据; -
MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map flashAttributes):指定请求的flash信息,比如重定向后的属性信息; -
MockHttpServletRequestBuildersession(MockHttpSession session) :指定请求的Session; -
MockHttpServletRequestBuilder principal(Principal principal) :指定请求的Principal; -
MockHttpServletRequestBuilder contextPath(String contextPath) :指定请求的上下文路径,必须以“/”开头,且不能以“/”结尾; -
MockHttpServletRequestBuilder pathInfo(String pathInfo) :请求的路径信息,必须以“/”开头; -
MockHttpServletRequestBuilder secure(boolean secure):请求是否使用安全通道; -
MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor):请求的后处理器,用于自定义一些请求处理的扩展点;
MockMultipartHttpServletRequestBuilder:
继承自MockHttpServletRequestBuilder,又提供了如下API:
MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上传的文件;
ResultActions:
调用MockMvc.perform(RequestBuilder requestBuilder)后将得到ResultActions,通过ResultActions完成如下三件事:
-
ResultActions andExpect(ResultMatcher matcher) :添加验证断言来判断执行请求后的结果是否是预期的; -
ResultActions andDo(ResultHandler handler) :添加结果处理器,用于对验证成功后执行的动作,如输出下请求/结果信息用于调试; -
MvcResult andReturn() :返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;
ResultMatcher/MockMvcResultMatchers:
ResultMatcher用来匹配执行完请求后的结果验证,其就一个match(MvcResult result)断言方法,如果匹配失败将抛出相应的异常
具体提供以下API:
-
HandlerResultMatchers handler():请求的Handler验证器,比如验证处理器类型/方法名;此处的Handler其实就是处理请求的控制器; -
RequestResultMatchers request():得到RequestResultMatchers验证器; -
ModelResultMatchers model():得到模型验证器; -
ViewResultMatchers view():得到视图验证器; -
FlashAttributeResultMatchers flash():得到Flash属性验证; -
StatusResultMatchers status():得到响应状态验证器; -
HeaderResultMatchers header():得到响应Header验证器; -
CookieResultMatchers cookie():得到响应Cookie验证器; -
ContentResultMatchers content():得到响应内容验证器; -
JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath(String expression, Matcher matcher):得到Json表达式验证器; -
XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map namespaces, Object... args):得到Xpath表达式验证器; -
ResultMatcher forwardedUrl(final String expectedUrl):验证处理完请求后转发的url(绝对匹配); -
ResultMatcher forwardedUrlPattern(final String urlPattern):验证处理完请求后转发的url(Ant风格模式匹配,@since spring4); -
ResultMatcher redirectedUrl(final String expectedUrl):验证处理完请求后重定向的url(绝对匹配); -
ResultMatcher redirectedUrlPattern(final String expectedUrl):验证处理完请求后重定向的url(Ant风格模式匹配,@since spring4);
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!
最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】




