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,参照下面代码:

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  2.  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  3.  <modelVersion>4.0.0</modelVersion>

  4.  <groupId>org.lvgang</groupId>

  5.  <artifactId>springboot-junit</artifactId>

  6.  <version>1.0-SNAPSHOT</version>

  7.  <packaging>jar</packaging>

  8.  <name>springboot-junit</name>

  9.  <url>http://maven.apache.org</url>

  10.  <parent>

  11.    <groupId>org.springframework.boot</groupId>

  12.    <artifactId>spring-boot-starter-parent</artifactId>

  13.    <version>2.1.3.RELEASE</version>

  14.  </parent>

  15.  <properties>

  16.    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  17.  </properties>

  18.  <dependencies>

  19.    <dependency>

  20.      <groupId>org.springframework.boot</groupId>

  21.      <artifactId>spring-boot-starter-web</artifactId>

  22.    </dependency>

  23.    <dependency>

  24.      <groupId>org.springframework.boot</groupId>

  25.      <artifactId>spring-boot-starter-test</artifactId>

  26.    </dependency>

  27.  </dependencies>

  28. </project>

创建一个Controller类,我们在后面就测试空上Controller

图片

02 编写测试类

下面我们就是编写测试类了:

  1. package org.lvgang;

  2. import org.junit.Assert;

  3. import org.junit.Before;

  4. import org.junit.Test;

  5. import org.junit.runner.RunWith;

  6. import org.springframework.beans.factory.annotation.Autowired;

  7. import org.springframework.boot.test.context.SpringBootTest;

  8. import org.springframework.http.MediaType;

  9. import org.springframework.test.context.junit4.SpringRunner;

  10. import org.springframework.test.context.web.WebAppConfiguration;

  11. import org.springframework.test.web.servlet.MockMvc;

  12. import org.springframework.test.web.servlet.MvcResult;

  13. import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

  14. import org.springframework.test.web.servlet.result.MockMvcResultHandlers;

  15. import org.springframework.test.web.servlet.setup.MockMvcBuilders;

  16. import org.springframework.web.context.WebApplicationContext;

  17. //SpringBoot1.4版本之前用的是SpringJUnit4ClassRunner.class

  18. @RunWith(SpringRunner.class)

  19. //SpringBoot1.4版本之前用的是@SpringApplicationConfiguration(classes = Application.class)

  20. @SpringBootTest(classes = App.class)

  21. //测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的

  22. @WebAppConfiguration

  23. public class HelloControllerTest {    

  24.    @Autowired

  25.    private WebApplicationContext webApplicationContext;    

  26.    private MockMvc mockMvc;    

  27.    

  28.    @Before

  29.    public void setUp() throws Exception{      

  30.        //MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc

  31.        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种

  32.    }    

  33.    @Test

  34.    public void getHello() throws Exception{        

  35.        /**

  36.         * 1、mockMvc.perform执行一个请求。

  37.         * 2、MockMvcRequestBuilders.get("XXX")构造一个请求。

  38.         * 3、ResultActions.param添加请求传值

  39.         * 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型

  40.         * 5、ResultActions.andExpect添加执行完成后的断言。

  41.         * 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情

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

  43.         * 5、ResultActions.andReturn表示执行完成后返回相应的结果。

  44.        */

  45.        MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/")

  46.                .param("name","lvgang")

  47.                .accept(MediaType.TEXT_HTML_VALUE))              

  48.               // .andExpect(MockMvcResultMatchers.status().isOk())             //等同于Assert.assertEquals(200,status);

  49.               // .andExpect(MockMvcResultMatchers.content().string("hello lvgang"))    //等同于 Assert.assertEquals("hello lvgang",content);

  50.                .andDo(MockMvcResultHandlers.print())

  51.                .andReturn();        

  52.        int status=mvcResult.getResponse().getStatus();                 //得到返回代码

  53.        String content=mvcResult.getResponse().getContentAsString();    //得到返回结果

  54.        Assert.assertEquals(200,status);                        //断言,判断返回代码是否正确

  55.        Assert.assertEquals("hello lvgang",content);            //断言,判断返回的值是否正确

  56.    }

  57. }

整个测试过程如下:

  • 准备测试环境

  • 通过MockMvc执行请求

  • 添加验证断言

  • 添加结果处理器

  • 得到MvcResult进行自定义断言/进行下一步的异步请求

  • 卸载测试环境

03 测试结果

通过执行HelloControllerTest,得到以下结果:

图片

并且把整个返回结果都打印到了Console中

  1. MockHttpServletRequest:

  2.      HTTP Method = GET

  3.      Request URI = /

  4.       Parameters = {name=[lvgang]}

  5.          Headers = {Accept=[text/html]}

  6. Handler:

  7.             Type = org.lvgang.HelloController

  8.           Method = public java.lang.String org.lvgang.HelloController.hello(java.lang.String)

  9. Async:

  10.    Async started = false

  11.    Async result = null

  12. Resolved Exception:

  13.             Type = null

  14. ModelAndView:

  15.       View name = null

  16.        View = null

  17.        Model = null

  18. FlashMap:

  19.       Attributes = null

  20. MockHttpServletResponse:

  21.           Status = 200

  22.    Error message = null

  23.          Headers = {Content-Type=[text/html;charset=UTF-8], Content-Length=[12]}

  24.     Content type = text/html;charset=UTF-8

  25.             Body = hello lvgang

  26.    Forwarded URL = null

  27.   Redirected URL = null

  28.          Cookies = []

通过以上代码,我们就完成了一个简单的案例。

附:

RequestBuilder/MockMvcRequestBuilders:

在上面的测试类中,我们用到了这么一个类MockMvcRequestBuilders用来构建请求的,此类有以下主要的API:

  1. MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的MockHttpServletRequestBuilder;如get(/user/{id}, 1L);

  2. MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables):同get类似,但是是POST方法;

  3. MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables):同get类似,但是是PUT方法;

  4. MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) :同get类似,但是是DELETE方法;

  5. MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables):同get类似,但是是OPTIONS方法;

  6. MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables):提供自己的Http请求方法及uri模板和uri变量,如上API都是委托给这个API;

  7. MockMultipartHttpServletRequestBuilderfile Upload(String urlTemplate, Object... urlVariables):提供文件上传方式的请求,得到MockMultipartHttpServletRequestBuilder;

  8. RequestBuilder asyncDispatch(final MvcResult mvcResult):创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder;

MockMvcRequestBuilders通过方法得到两类Builder:

  • 一个是MockHttpServletRequestBuilder

  • 一个是MockMultipartHttpServletRequestBuilder (上传文件)

MockHttpServletRequestBuilder:

主要有以下API:

  1. MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders):添加头信息;

  2. MockHttpServletRequestBuilder contentType(MediaType mediaType):指定请求的contentType头信息;

  3. MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes):指定请求的Accept头信息;

  4. MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content):指定请求Body体内容;

  5. MockHttpServletRequestBuilder param(String name,String... values):请求传入参数

  6. MockHttpServletRequestBuilder cookie(Cookie... cookies):指定请求的Cookie;

  7. MockHttpServletRequestBuilder locale(Locale locale):指定请求的Locale;

  8. MockHttpServletRequestBuildercharacterEncoding(String encoding):指定请求字符编码;

  9. MockHttpServletRequestBuilder requestAttr(String name, Object value) :设置请求属性数据;

  10. MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<string, object=""> sessionAttributes):设置请求session属性数据;

  11. MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map<string, object=""> flashAttributes):指定请求的flash信息,比如重定向后的属性信息;

  12. MockHttpServletRequestBuildersession(MockHttpSession session) :指定请求的Session;

  13. MockHttpServletRequestBuilder principal(Principal principal) :指定请求的Principal;

  14. MockHttpServletRequestBuilder contextPath(String contextPath) :指定请求的上下文路径,必须以“/”开头,且不能以“/”结尾;

  15. MockHttpServletRequestBuilder pathInfo(String pathInfo) :请求的路径信息,必须以“/”开头;

  16. MockHttpServletRequestBuilder secure(boolean secure):请求是否使用安全通道;

  17. MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor):请求的后处理器,用于自定义一些请求处理的扩展点;

MockMultipartHttpServletRequestBuilder:

继承自MockHttpServletRequestBuilder,又提供了如下API:

MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上传的文件;

ResultActions:

调用MockMvc.perform(RequestBuilder requestBuilder)后将得到ResultActions,通过ResultActions完成如下三件事:

  1. ResultActions andExpect(ResultMatcher matcher) :添加验证断言来判断执行请求后的结果是否是预期的;

  2. ResultActions andDo(ResultHandler handler) :添加结果处理器,用于对验证成功后执行的动作,如输出下请求/结果信息用于调试;

  3. MvcResult andReturn() :返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;

ResultMatcher/MockMvcResultMatchers:

ResultMatcher用来匹配执行完请求后的结果验证,其就一个match(MvcResult result)断言方法,如果匹配失败将抛出相应的异常

具体提供以下API:

  1. HandlerResultMatchers handler():请求的Handler验证器,比如验证处理器类型/方法名;此处的Handler其实就是处理请求的控制器;

  2. RequestResultMatchers request():得到RequestResultMatchers验证器;

  3. ModelResultMatchers model():得到模型验证器;

  4. ViewResultMatchers view():得到视图验证器;

  5. FlashAttributeResultMatchers flash():得到Flash属性验证;

  6. StatusResultMatchers status():得到响应状态验证器;

  7. HeaderResultMatchers header():得到响应Header验证器;

  8. CookieResultMatchers cookie():得到响应Cookie验证器;

  9. ContentResultMatchers content():得到响应内容验证器;

  10. JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath(String expression, Matcher matcher):得到Json表达式验证器;

  11. XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map<string, string=""> namespaces, Object... args):得到Xpath表达式验证器;

  12. ResultMatcher forwardedUrl(final String expectedUrl):验证处理完请求后转发的url(绝对匹配);

  13. ResultMatcher forwardedUrlPattern(final String urlPattern):验证处理完请求后转发的url(Ant风格模式匹配,@since spring4);

  14. ResultMatcher redirectedUrl(final String expectedUrl):验证处理完请求后重定向的url(绝对匹配);

  15. ResultMatcher redirectedUrlPattern(final String expectedUrl):验证处理完请求后重定向的url(Ant风格模式匹配,@since spring4);

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值