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 的配置,可以根据自己的需求选择一 ...
随机推荐
- WSASocket()创建套接字不成功解决方法
这几天我在写一个模仿windows自带的ping程序,可是套接字总是创建不成功,在网上找了一些资料最后总算把问题解决了,现在总结一下. 解决方法:以管理员运行VS就行了我的是vs2013,vs2010 ...
- HTML--CSS样式表--格式与布局
一:position:fixed 锁定位置(相对于浏览器的位置),例如有些网站的右下角弹窗 例如: <head> <title>网页标题</title> <s ...
- 研究分布式唯一ID生成,看完这篇就够
很多大的互联网公司数据量很大,都采用分库分表,那么分库后就需要统一的唯一ID进行存储.这个ID可以是数字递增的,也可以是UUID类型的. 如果是递增的话,那么拆分了数据库后,可以按照id的hash,均 ...
- solr集群
一.所需环境 1.linux系统(内存分大点) 2.JDK 3.zookeeper 4.solr 二.安装zookeeper 1.此次安装3个zookeeper 2.tar -zxf zookeepe ...
- PHP Composer安装使用
1.安装composer curl -sS https:\\getcomposer.org/install | php 如果出现这样的提示,打开php.ini检查是否开启openssl扩展 2.下载成 ...
- 【iOS】duplicate symbols for architecture x86_64
今天遇到了这个问题,错误如下: duplicate symbol _OBJC_IVAR_$_BCViewController.bank in: /Users/***/Library/Developer ...
- Code blocks返回错误代码:Process returned -1073741819 (0xC0000005)
循环语句访问链表时,返回了错误代码: 逐项排查后,发现是由while循环引起的: 附上出错代码: do{ L=L->post; printf("%05d %d %05d\n" ...
- Redis分布式锁实战
什么是分布式锁 在单机部署的情况下,要想保证特定业务在顺序执行,通过JDK提供的synchronized关键字.Semaphore.ReentrantLock,或者我们也可以基于AQS定制化锁.单机部 ...
- Mysql的行级锁与表级锁
在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM ...
- Day01:JAVA开发环境
下载JDK 首先我们需要下载java开发工具包JDK,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html,点 ...