Spring学习之旅(十)--MockMvc
在之前的 Spring学习之旅(八)--SpringMVC请求参数 我们是通过在控制台输出来验证参数是否正确,但是这样做实在是太耗时间了,我们今天来学习下 MockMvc,它可以让我们不需要启动项目就能调用接口并验证接口返回结果是否符合我们的预期。
为何使用MockMvc?
MockMvc 实现了对 Http 请求的模拟,能够直接使用网络的形式,实现 Controller 的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
如何使用 MockMvc
MockMvcBuilder 是用来构造 MockMvc 的构造器,主要有两个实现:
- StandaloneMockMvcBuilder
- DefaultMockMvcBuilder
分别对应两种测试方式,即独立安装和集成 Web 环境测试(此种方式并不会集成真正的 web 环境,而是通过相应的 Mock API 进行模拟测试,无须启动服务器)。对于我们来说直接使用静态工厂 MockMvcBuilders 创建即可。
集成Web环境方式
MockMvcBuilders.webAppContextSetup(WebApplicationContext context)
:指定 WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的 MockMvc;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RootConfig.class)
@WebAppConfiguration
public class RequestParameterControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
}
独立测试方式
MockMvcBuilders.standaloneSetup(Object... controllers)
:通过参数指定一组控制器,这样就不需要从上下文获取了;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RootConfig.class)
@WebAppConfiguration
public class RequestParameterControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(new RequestParameterController()).build();
}
}
实例
Controller:
@Controller
public class RequestParameterController {
@RequestMapping("/toInt")
@ResponseBody
public int toInt(int value) {
return value;
}
}
单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RootConfig.class)
@WebAppConfiguration
public class RequestParameterControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void toInt() throws Exception {
mockMvc.perform(
// 发送 GET 请求
MockMvcRequestBuilders.get("/toInteger?value=3"))
// 判断HTTP响应码
.andExpect(MockMvcResultMatchers.status().isOk())
// 判断返回内容是否是预期值
.andExpect(MockMvcResultMatchers.content().string("3"))
// 输出整个响应结果信息
.andDo(MockMvcResultHandlers.print());
}
}
控制台输出:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /toInteger
Parameters = {value=[3]}
Headers = {}
Handler:
Type = com.marklogzhu.web.controller.RequestParameterController
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/plain;charset=ISO-8859-1], Content-Length=[1]}
Content type = text/plain;charset=ISO-8859-1
Body = 3
Forwarded URL = null
Redirected URL = null
Cookies = []
Process finished with exit code 0
常用对象
MockMvcRequestBuilders
MockMvcRequestBuilders: 用来构建请求。
方法 | 作用 |
---|---|
MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables) | 发送 GET 请求 |
MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables) | 发送 POST 请求 |
MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables) | 发送 PUT 请求 |
MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) | 发送 DELETE 请求 |
MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables) | 发送 OPTIONS 请求 |
MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables) | 提供自己的Http请求方法及uri模板和uri变量 |
MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables) | 发送文件上传请求 |
RequestBuilder asyncDispatch(final MvcResult mvcResult) | 创建一个启动异步处理的请求的 MvcResult 进行异步分派的RequestBuilder |
ResultActions
调用 MockMvc.perform(RequestBuilder requestBuilder)
后将得到 ResultActions,通过 ResultActions 可以完成如下三件事:
- ResultActions andExpect(ResultMatcher matcher) :添加验证断言来判断执行请求后的结果是否是预期的;
- ResultActions andDo(ResultHandler handler) :添加结果处理器,用于对验证成功后执行的动作,如输出下请求/结果信息用于调试;
- MvcResult andReturn() :返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;
ResultMatcher
方法 | 作用 |
---|---|
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) | 得到Json表达式验证器 |
ResultMatcher jsonPath(String expression, Matcher matcher) | 得到Json表达式验证器 |
XpathResultMatchers xpath(String expression, Object... args) | 得到Xpath表达式验证器 |
XpathResultMatchers xpath(String expression, Map<string, string=""> 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) |
实例
JSON请求/响应验证
String requestBody = "{\"id\":1, \"name\":\"zhang\"}";
mockMvc.perform(post("/user")
.contentType(MediaType.APPLICATION_JSON).content(requestBody)
.accept(MediaType.APPLICATION_JSON)) //执行请求
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) //验证响应contentType
.andExpect(jsonPath("$.id").value(1)); //使用Json path 验证JSON,具体表达式规则请参考 http://goessner.net/articles/JsonPath/
String errorBody = "{id:1, name:zhang}";
MvcResult result = mockMvc.perform(post("/user")
.contentType(MediaType.APPLICATION_JSON).content(errorBody)
.accept(MediaType.APPLICATION_JSON)) //执行请求
.andExpect(status().isBadRequest()) //400错误请求
.andReturn();
Assert.assertTrue(HttpMessageNotReadableException.class.isAssignableFrom(result.getResolvedException().getClass()));//错误的请求内容体
文件上传
byte[] bytes = new byte[] {1, 2};
mockMvc.perform(fileUpload("/user/{id}/icon", 1L).file("icon", bytes)) //执行文件上传
.andExpect(model().attribute("icon", bytes)) //验证属性相等性
.andExpect(view().name("success")); //验证视图
自定义验证
MvcResult result = mockMvc.perform(get("/user/{id}", 1))//执行请求
.andReturn(); //返回MvcResult
Assert.assertNotNull(result.getModelAndView().getModel().get("user")); //自定义断言
Spring学习之旅(十)--MockMvc的更多相关文章
- Spring学习之旅(十五)--SpringBoot
在使用 Spring 的过程中,有时候会出现一些 ClassNotFoundException 异常,这是因为 JAR 依赖之间的版本不匹配所导致的.而 Spring Boot 就能避免绝大多数依赖版 ...
- Spring学习之旅(十四)--缓存
数据库的读写并发一直都是应用性能的瓶颈所在之一,针对改动频率很小的数据我们应该将他存放到缓存中,减少与数据库的交互. 启用对缓存的支持 Spring 对缓存的支持有两种方式: 注解驱动的缓存 XML ...
- Spring学习之旅(十二)--持久化框架
对于本职工作来说 JDBC 就可以很好的完成,但是当我们对持久化的需求变得更复杂时,如: 延迟加载 预先抓取 级联 JDBC 就不能满足了,我们需要使用 ORM框架 来实现这些需求. Spring 对 ...
- Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)
在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...
- Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探
由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...
- Spring学习之旅(六)--SpringMVC集成
对大多数 Java 开发来说,基于 web 的应用程序是我们主要的关注点. Spring 也提供了对于 web 的支持,基于 MVC 模式的 Spring MVC 能够帮助我们灵活和松耦合的完成 we ...
- Java框架spring 学习笔记(十四):注解aop操作
回见Java框架spring Boot学习笔记(十三):aop实例操作,这里介绍注解aop操作 首先编写一个切入点HelloWorld.java package com.example.spring; ...
- Spring学习之旅(十三)--使用NoSQL数据库
除了关系型数据库之外,现在还有一种 NoSQL 数据库非常流行,而 Spring 自然也没有放过对它的支持. NoSQL 数据库有很多种,如: MongoDBGenericJackson2JsonRe ...
- Spring学习之旅(三)--装配Bean
装配 Bean 的方式 在 XML 中进行显式配置 在 Java 中进行显式配置 隐式的 Bean 发现机制和自动装配 Spring 提供了以上三种方式进行 Bean 的配置,可以根据自己的需求选择一 ...
随机推荐
- python基础知识练习题一
1.执行Python脚本的两种方式 1.在计算机终端(运行cmd),输入安装的Python路径,然后输入Python脚本的路径,回车. 2.直接运行python 2.简述位.字节的关系. 1字节 = ...
- asn1学习笔记 约束
继续看asn1语法详解,今天主要看了约束部分,包含 1.单值约束,包含枚举类型 enumerated . 如: Two ::= INTEGER(2) Day ::= ENUMERATED { mond ...
- 优化 Ubuntu
优化Ubuntu 1. 更换 apt 源 echo 'deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe mul ...
- kubernetes CRD 开发指南
扩展kubernetes两个最常用最需要掌握的东西:自定义资源CRD 和 adminsion webhook, 本文教你如何十分钟掌握CRD开发. kubernetes允许用户自定义自己的资源对象,就 ...
- 使用钉钉对接禅道的bug系统,实现禅道提的bug实时在钉钉提醒并艾特对应的开发人员处理
现在公司测试中有一个痛点是每次测试人员提完bug后,需要定期去提醒开发人员查看禅道的bug记录及修复bug. 导致测试人员在项目测试中不仅要测试整个软件,还要负起实时监督提醒功能的“保姆角色”,身心疲 ...
- C++实现反射
之前碰到过一个问题,C++中如何通过一个字符串生成一个类. C++是不支持通过类名称字符串”ClassXX”来生成对象的,也就是说我们可以使用 new ClassXX 来生成对象,但是不能通过 new ...
- 【Python-Django定义用户模型类】Python-Django定义用户模型类详解!!!
定义用户模型类 1. Django默认用户认证系统 Django自带用户认证系统 它处理用户账号.组.权限以及基于cookie的用户会话. Django认证系统位置 django.contrib.au ...
- CMD开放3389端口
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t R ...
- tab选项卡代码
$('.case_header ul li').click(function(){ $(this).addClass('active').siblings().removeClass('active' ...
- python3 编译安装
前言: Linux下大部分系统默认自带python2.x的版本,最常见的是python2.6或python2.7版本,默认的python被系统很多程序所依赖,比如centos下的yum就是python ...