对模块进行集成测试时,希望能够通过输入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,参照下面代码

  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

  1. package org.lvgang;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. @RestController
  5. public class HelloController {
  6. @RequestMapping("/")
  7. public String hello(String name){
  8. return "hello "+name;
  9. }
  10. }

第二步、编写测试类

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

  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. @Before
  28. public void setUp() throws Exception{
  29. //MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc;
  30. mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
  31. }
  32. @Test
  33. public void getHello() throws Exception{
  34. /**
  35. * 1、mockMvc.perform执行一个请求。
  36. * 2、MockMvcRequestBuilders.get("XXX")构造一个请求。
  37. * 3、ResultActions.param添加请求传值
  38. * 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型
  39. * 5、ResultActions.andExpect添加执行完成后的断言。
  40. * 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
  41. * 比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
  42. * 5、ResultActions.andReturn表示执行完成后返回相应的结果。
  43. */
  44. MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/")
  45. .param("name","lvgang")
  46. .accept(MediaType.TEXT_HTML_VALUE))
  47. // .andExpect(MockMvcResultMatchers.status().isOk()) //等同于Assert.assertEquals(200,status);
  48. // .andExpect(MockMvcResultMatchers.content().string("hello lvgang")) //等同于 Assert.assertEquals("hello lvgang",content);
  49. .andDo(MockMvcResultHandlers.print())
  50. .andReturn();
  51. int status=mvcResult.getResponse().getStatus(); //得到返回代码
  52. String content=mvcResult.getResponse().getContentAsString(); //得到返回结果
  53. Assert.assertEquals(200,status); //断言,判断返回代码是否正确
  54. Assert.assertEquals("hello lvgang",content); //断言,判断返回的值是否正确
  55. }
  56. }

整个测试过程如下:

1、准备测试环境

2、通过MockMvc执行请求

3、添加验证断言

4、添加结果处理器

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

6、卸载测试环境

第三步、测试结果

通过执行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. MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables):提供文件上传方式的请求,得到MockMultipartHttpServletRequestBuilder
  8. RequestBuilder asyncDispatch(final MvcResult mvcResult):创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder

MockMvcRequestBuilders通过方法得到两类Builder,一个是MockHttpServletRequestBuilder ,一个是MockMultipartHttpServletRequestBuilder (上传文件)

MockHttpServletRequestBuilder:

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. MockHttpServletRequestBuilder characterEncoding(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. MockHttpServletRequestBuilder session(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:

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

  1. 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):验证处理完请求后转发的urlAnt风格模式匹配,@since spring4);
  14. ResultMatcher redirectedUrl(final String expectedUrl):验证处理完请求后重定向的url(绝对匹配);
  15. ResultMatcher redirectedUrlPattern(final String expectedUrl):验证处理完请求后重定向的urlAnt风格模式匹配,@since spring4);
  16. https://my.oschina.net/sdlvzg/blog/1594821

SpringBoot使用MockMVC单元测试Controller的更多相关文章

  1. springboot使用MockMvc测试controller

    通常,在我们平时开发项目时,如果想要输入URL对Controller进行测试,在代码编辑之后,需要重启服务器,建立http client进行测试.这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不 ...

  2. spring-mvc springboot 使用MockMvc对controller进行测试

    网上基本都是参考官方的使用方式,使用了import static,个人感觉这种方式特别不好,代码提示性不友好.所以在此进行说明,也方便自己以后使用. 1. 引入spring-test相关jar包,sp ...

  3. springboot利用MockMvc测试controller控制器

    主要记录一下控制器的测试,service这些类测试相对简单些(可测试性强) API测试需求比较简单: ① 需要返回正确的http状态码 200 ② 需要返回json数据,并且不能返回未经捕获的系统异常 ...

  4. springboot Service层单元测试

    两个实现类实现同一个Service接口 public interface CustomUrlService { List<ShopMetrics> getShopMetrics(); } ...

  5. 【快学springboot】在springboot中写单元测试[Happyjava]

    前言 很多公司都有写单元测试的硬性要求,在提交代码的时候,如果单测通不过或者说单元测试各种覆盖率不达标,会被拒绝合并代码.写单元测试,也是保证代码质量的一种方式. junit单元测试 相信绝大多数的J ...

  6. 【快学springboot】在springboot中写单元测试

    前言 很多公司都有写单元测试的硬性要求,在提交代码的时候,如果单测通不过或者说单元测试各种覆盖率不达标,会被拒绝合并代码.写单元测试,也是保证代码质量的一种方式. junit单元测试 相信绝大多数的J ...

  7. SpringBoot 中常用注解@Controller/@RestController/@RequestMapping的区别

    SpringBoot中常用注解@Controller/@RestController/@RequestMapping的区别 @Controller 处理http请求 @Controller //@Re ...

  8. SpringBoot 中常用注解@Controller/@RestController/@RequestMapping介绍

    原文 SpringBoot 中常用注解 @Controller/@RestController/@RequestMapping介绍 @Controller 处理http请求 @Controller / ...

  9. springBoot中“MockMvc”的进行Controller进行单元测试:application/octet-stream' not supported问题小结

    解决方案:这个问题其实是Content-type的问题,只需要在相关的代码加入相关Content-type中就可以了,代码如下: mockMvc.perform(post("/user&qu ...

随机推荐

  1. Python3 queue队列类

    class queue.PriorityQueue(maxsize=0) 优先级队列构造函数. maxsize 是个整数,用于设置可以放入队列中的项目数的上限.当达到这个大小的时候,插入操作将阻塞至队 ...

  2. 安防视频互联网化的EasyDSS流媒体服务器不但能Easy安防流媒体的开发而且能更加互联网化视频协议的输出

    开发EasyDSS的初衷 自从12年开始做EasyDarwin的时候,当时眼光一直都仅仅局限在安防监控视频这一块,对RTMP没有太大的重视,对于后起之秀HLS更是没有太多关注,然而经历了15直播火热的 ...

  3. [LeetCode] 687. Longest Univalue Path 最长唯一值路径

    Given a binary tree, find the length of the longest path where each node in the path has the same va ...

  4. PKUWC2020自闭记

    我才听说PKU今年对我省高二要求CSP分数>450? 我似乎丧失了一个溜去隔壁的机会? 机会是不存在的qwq THUWC3个数据结构直接送人升天 Day1 T1:感觉相邻的k!个排列是同构的可以 ...

  5. Oracle Spatial 中的弧段及弧相关拓扑错误

    1.报告说明 此报告用于验证下列问题: ORACLE SPATIAL 0.05m的最小拓扑容差值是否可以被修改 原始数据通过ARCGIS入库数据精度是否有损失 修改ORACLE SPATIAL图层的最 ...

  6. 【转】Fuel 9.0安装Openstack网络验证失败解决

    原文链接:https://blog.csdn.net/wiborgite/article/details/52983575 故障现象: 网络验证失败,报错信息如下: Repo availability ...

  7. Spring中的乱码问题

    最近发现一个问题, 中文编码保存到数据库里显示正确, 打印出来却是一串问号, 然后怀疑是平台默认编码的问题, locale命令显示是UTF-8正常, 然后单独编写一个java文件, 编译然后Java命 ...

  8. Windows 下删除 Docker 容器的方法

    Issue: 删除命令执行失败 如果在 CMD 命令提示符下删除容器可能失败,可切换至 PowerShell 中执行成功. unknown shorthand flag: 'a' in -a See ...

  9. Java开发笔记(一百四十)JavaFX的选择框

    与Swing一样,JavaFX依然提供了三种选择框,它们是复选框CheckBox.单选按钮RadioButton.下拉框ComboBox,分别说明如下: 一.复选框CheckBox复选框允许同时勾选多 ...

  10. python学习-66 面向对象3 - 多态

    多态 1.什么是多态 由不同的类实例化得到的对象,调用同一个方法,执行的逻辑不同. 举例: class H2O: def __init__(self,type,tem): self.type = ty ...