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取数字、字母
python取数字.字母 有一串字符串“lxa7YzU”,其中有大写字母.小写字母和数字,现编写一脚本使得实现以下功能: 将这串字符串中的数字.大写字母.小写字母分别取出来并进行分类. 脚本如下所示: ...
- docker学习ppt
保存下学习资料
- mongodb的索引原理
首先说一下为什么要有索引,大家都知道mongdb是非关系型文档类型数据库,用过的人都有同一种感受,查询的效率太低,当你想提高查询效率的时候可以就需要使用索引了. 哈哈,本来想写一篇的,在网上看到了一篇 ...
- LeetCode 448. Find All Numbers Disappeared in an Array找到所有数组中消失的元素
题目 给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次. 找到所有在 [1, n] 范围之间没有出现在数组中的数字. 您能 ...
- 15. Java异常处理
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- 【Java】Exception thrown by the agent : java.rmi.server.ExportException: Port already in use: 1099
详细信息如下: Error: Exception thrown by the agent : java.rmi.server.ExportException: Port already in use: ...
- spring实战学习笔记(一)spring装配bean
最近在学习spring boot 发现对某些注解不是很深入的了解.看技术书给出的实例 会很疑惑为什么要用这个注解? 这个注解的作用?有其他相同作用的注解吗?这个注解的运行机制是什么?等等 spring ...
- 测试通过mweb进行发布Title
MWeb 是专业的 Markdown 写作.记笔记.静态博客生成软件,目前已支持 Mac,iPad 和 iPhone.MWeb 有以下特色: 软件本身: 使用原生的 macOS 技术打造,追求与系统的 ...
- Linux基础管道管理
一.I/O重定向 标准输入,标准输出,标准错误 file descriptors (FD, 文件描述符或Process I/O channels); 进程使用文件描述符来管理打开的文件 [root@l ...
- Python - 自学django,上线一套资产管理系统
一.概述 终于把公司的资产管理网站写完,并通过测试,然后上线.期间包括看视频学习.自己写前后端代码,用时两个多月.现将一些体会记录下来,希望能帮到想学django做web开发的人.大牛可以不用看了,小 ...