在之前的 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的更多相关文章

  1. Spring学习之旅(十五)--SpringBoot

    在使用 Spring 的过程中,有时候会出现一些 ClassNotFoundException 异常,这是因为 JAR 依赖之间的版本不匹配所导致的.而 Spring Boot 就能避免绝大多数依赖版 ...

  2. Spring学习之旅(十四)--缓存

    数据库的读写并发一直都是应用性能的瓶颈所在之一,针对改动频率很小的数据我们应该将他存放到缓存中,减少与数据库的交互. 启用对缓存的支持 Spring 对缓存的支持有两种方式: 注解驱动的缓存 XML ...

  3. Spring学习之旅(十二)--持久化框架

    对于本职工作来说 JDBC 就可以很好的完成,但是当我们对持久化的需求变得更复杂时,如: 延迟加载 预先抓取 级联 JDBC 就不能满足了,我们需要使用 ORM框架 来实现这些需求. Spring 对 ...

  4. Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)

    在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...

  5. Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探

    由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...

  6. Spring学习之旅(六)--SpringMVC集成

    对大多数 Java 开发来说,基于 web 的应用程序是我们主要的关注点. Spring 也提供了对于 web 的支持,基于 MVC 模式的 Spring MVC 能够帮助我们灵活和松耦合的完成 we ...

  7. Java框架spring 学习笔记(十四):注解aop操作

    回见Java框架spring Boot学习笔记(十三):aop实例操作,这里介绍注解aop操作 首先编写一个切入点HelloWorld.java package com.example.spring; ...

  8. Spring学习之旅(十三)--使用NoSQL数据库

    除了关系型数据库之外,现在还有一种 NoSQL 数据库非常流行,而 Spring 自然也没有放过对它的支持. NoSQL 数据库有很多种,如: MongoDBGenericJackson2JsonRe ...

  9. Spring学习之旅(三)--装配Bean

    装配 Bean 的方式 在 XML 中进行显式配置 在 Java 中进行显式配置 隐式的 Bean 发现机制和自动装配 Spring 提供了以上三种方式进行 Bean 的配置,可以根据自己的需求选择一 ...

随机推荐

  1. ThinkPHP 入门

    ThinkPHP是一个免费.开源的,快速.简单地面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,是为了敏捷Web应用开发和简化企业级应用开发而诞生的.ThinkPHP借鉴国外很多优秀的 ...

  2. CCNA笔记(一)

    R1#enable R1#configure terminal R1(config)#interface fastEthernet 0/0R1(config-if)#ip address 12.1.1 ...

  3. js - 使用jquery发送前台请求给服务器,并显示数据

    1.使用jquery发送前台请求给服务器,并显示数据 <%@ page contentType="text/html;charset=UTF-8" language=&quo ...

  4. 前后端分离 之vue-cli 搭建项目mac 系统讲解

    前端项目搭建必备技术 webpack nodejs 搭建 vue-cli 的安装 以上技术自行了解安装 一:创建前端项目 采用vue-cli 脚手架 1:终端执行如下命令 vue init webpa ...

  5. django+uwsgi+nginx 部署生产环境

    一.Uwsgi安装 python3 -m pip install uwsgi cp /usr/local/python3/bin/uwsgi /usr/bin/ 测试 在django项目主目录下cre ...

  6. 深入理解JVM-类加载器深入解析(3)

    深入理解JVM-类加载器深入解析(3) 获得ClassLoader的途径 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader ...

  7. Java 设置PDF文档浏览偏好

    在查看PDF文档时,可进行一些浏览偏好设置,例如是否全屏浏览.隐藏或显示菜单栏/工具栏.设置页面布局模式等,下面将通过Java编程的方式来演示如何设置. 使用工具: Free Spire.PDF fo ...

  8. go 学习笔记之走进Goland编辑器

    工欲善其事必先利其器,命令行工具虽然能够在一定程度上满足基本操作的需求,但实际工作中总不能一直使用命令行工具进行编码操作吧? 学习 Go 语言同样如此,为此需要寻找一个强大的 IDE 集成环境帮助我们 ...

  9. prometheus-kafka-exporter部署

    chart地址:https://gkarthiks.github.io/helm-charts/charts/prometheus-kafka-exporter/ 1.下载chart $ helm r ...

  10. 【Java例题】4.5异常处理

    5. 对于输入的数,如果出现小数,则作为异常处理,并舍去小数,显示结果:如果输入的数据类型不对也作为异常处理,显示结果0. package chapter4; import java.util.*; ...