转载自https://my.oschina.net/sdlvzg/blog/1594821 若有侵权,请联系删除
对模块进行集成测试时,希望能够通过输入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,参照下面代码
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0
</modelVersion>
-
-
<groupId>org.lvgang
</groupId>
-
<artifactId>springboot-junit
</artifactId>
-
<version>1.0-SNAPSHOT
</version>
-
<packaging>jar
</packaging>
-
-
<name>springboot-junit
</name>
-
<url>http://maven.apache.org
</url>
-
-
<parent>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-parent
</artifactId>
-
<version>1.5.9.RELEASE
</version>
-
</parent>
-
-
<properties>
-
<project.build.sourceEncoding>UTF-8
</project.build.sourceEncoding>
-
</properties>
-
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-web
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-test
</artifactId>
-
</dependency>
-
</dependencies>
-
</project>
创建一个Controller类,我们在后面就测试空上Controller
-
package org.lvgang;
-
-
import org.springframework.web.bind.
annotation.RequestMapping;
-
import org.springframework.web.bind.
annotation.RestController;
-
-
@RestController
-
public
class HelloController {
-
-
@RequestMapping("/")
-
public String hello(String name){
-
return
"hello "+name;
-
}
-
-
}
第二步、编写测试类
下面我们就是编写测试类了
-
package org.lvgang;
-
-
import org.junit.Assert;
-
import org.junit.Before;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.http.MediaType;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import org.springframework.test.context.web.WebAppConfiguration;
-
import org.springframework.test.web.servlet.MockMvc;
-
import org.springframework.test.web.servlet.MvcResult;
-
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
-
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-
import org.springframework.web.context.WebApplicationContext;
-
-
//SpringBoot1.4版本之前用的是SpringJUnit4ClassRunner.class
-
@
RunWith(
SpringRunner.
class)
-
//SpringBoot1.4版本之前用的是@SpringApplicationConfiguration(classes = Application.class)
-
@
SpringBootTest(classes =
App.
class)
-
//测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的
-
@
WebAppConfiguration
-
public
class HelloControllerTest {
-
-
@
Autowired
-
private
WebApplicationContext webApplicationContext;
-
private
MockMvc mockMvc;
-
-
@
Before
-
public void setUp()
throws
Exception{
-
//MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc;
-
mockMvc =
MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
//建议使用这种
-
}
-
-
@
Test
-
public void getHello()
throws
Exception{
-
-
/**
-
* 1、mockMvc.perform执行一个请求。
-
* 2、MockMvcRequestBuilders.get("XXX")构造一个请求。
-
* 3、ResultActions.param添加请求传值
-
* 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型
-
* 5、ResultActions.andExpect添加执行完成后的断言。
-
* 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
-
* 比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
-
* 5、ResultActions.andReturn表示执行完成后返回相应的结果。
-
*/
-
-
MvcResult mvcResult= mockMvc.perform(
MockMvcRequestBuilders.
get(
"/")
-
.param(
"name",
"lvgang")
-
.accept(
MediaType.
TEXT_HTML_VALUE))
-
// .andExpect(MockMvcResultMatchers.status().isOk()) //等同于Assert.assertEquals(200,status);
-
// .andExpect(MockMvcResultMatchers.content().string("hello lvgang")) //等同于 Assert.assertEquals("hello lvgang",content);
-
.andDo(
MockMvcResultHandlers.
print())
-
.andReturn();
-
int status=mvcResult.getResponse().getStatus();
//得到返回代码
-
String content=mvcResult.getResponse().getContentAsString();
//得到返回结果
-
-
Assert.assertEquals(
200,status);
//断言,判断返回代码是否正确
-
Assert.assertEquals(
"hello lvgang",content);
//断言,判断返回的值是否正确
-
}
-
}
整个测试过程如下:
1、准备测试环境
2、通过MockMvc执行请求
3、添加验证断言
4、添加结果处理器
5、得到MvcResult进行自定义断言/进行下一步的异步请求
6、卸载测试环境
第三步、测试结果
通过执行HelloControllerTest,得到以下结果:
并且把整个返回结果都打印到了Console中
-
MockHttpServletRequest:
-
HTTP Method =
GET
-
Request URI = /
-
Parameters = {name=[lvgang]}
-
Headers = {Accept=[text/html]}
-
-
Handler:
-
Type = org.lvgang.HelloController
-
Method =
public java.lang.
String org.lvgang.HelloController.hello(java.lang.
String)
-
-
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/html;charset=UTF
-8], Content-Length=[
12]}
-
Content type = text/html;charset=UTF
-8
-
Body = hello lvgang
-
Forwarded URL =
null
-
Redirected URL =
null
-
Cookies = []
通过以上代码,我们就完成了一个简单的案例。
附:
RequestBuilder/MockMvcRequestBuilders:
在上面的测试类中,我们用到了这么一个类MockMvcRequestBuilders用来构建请求的,此类有以下主要的API:
-
MockHttpServletRequestBuilder get(
String urlTemplate,
Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的MockHttpServletRequestBuilder;如get(
/user/{id},
1L);
-
MockHttpServletRequestBuilder post(
String urlTemplate,
Object... urlVariables):同get类似,但是是POST方法;
-
MockHttpServletRequestBuilder put(
String urlTemplate,
Object... urlVariables):同get类似,但是是PUT方法;
-
MockHttpServletRequestBuilder
delete(
String urlTemplate,
Object... urlVariables) :同get类似,但是是DELETE方法;
-
MockHttpServletRequestBuilder options(
String urlTemplate,
Object... urlVariables):同get类似,但是是OPTIONS方法;
-
MockHttpServletRequestBuilder request(HttpMethod httpMethod,
String urlTemplate,
Object... urlVariables): 提供自己的Http请求方法及uri模板和uri变量,如上API都是委托给这个API;
-
MockMultipartHttpServletRequestBuilder fileUpload(
String urlTemplate,
Object... urlVariables):提供文件上传方式的请求,得到MockMultipartHttpServletRequestBuilder;
-
RequestBuilder asyncDispatch(final MvcResult mvcResult):创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder;
-
MockMvcRequestBuilders通过方法得到两类Builder,一个是MockHttpServletRequestBuilder ,一个是MockMultipartHttpServletRequestBuilder (上传文件)
MockHttpServletRequestBuilder:
MockHttpServletRequestBuilder 主要有一下API:
-
MockHttpServletRequestBuilder header(
String name,
Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders):添加头信息;
-
MockHttpServletRequestBuilder contentType(MediaType mediaType):指定请求的contentType头信息;
-
MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(
String... mediaTypes):指定请求的Accept头信息;
-
MockHttpServletRequestBuilder content(
byte[] content)/MockHttpServletRequestBuilder content(
String content):指定请求Body体内容;
-
MockHttpServletRequestBuilder param(
String name,
String... values):请求传入参数
-
MockHttpServletRequestBuilder cookie(Cookie... cookies):指定请求的Cookie;
-
MockHttpServletRequestBuilder locale(Locale locale):指定请求的Locale;
-
MockHttpServletRequestBuilder characterEncoding(
String encoding):指定请求字符编码;
-
MockHttpServletRequestBuilder requestAttr(
String name,
Object value) :设置请求属性数据;
-
MockHttpServletRequestBuilder sessionAttr(
String name,
Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<
string,
object=
""> sessionAttributes):设置请求session属性数据;
-
MockHttpServletRequestBuilder flashAttr(
String name,
Object value)/MockHttpServletRequestBuilder flashAttrs(Map<
string,
object=
""> flashAttributes):指定请求的flash信息,比如重定向后的属性信息;
-
MockHttpServletRequestBuilder session(MockHttpSession session) :指定请求的Session;
-
MockHttpServletRequestBuilder principal(Principal principal) :指定请求的Principal;
-
MockHttpServletRequestBuilder contextPath(
String contextPath) :指定请求的上下文路径,必须以“/”开头,且不能以“/”结尾;
-
MockHttpServletRequestBuilder pathInfo(
String pathInfo) :请求的路径信息,必须以“/”开头;
-
MockHttpServletRequestBuilder secure(
boolean secure):请求是否使用安全通道;
-
MockHttpServletRequestBuilder
with(RequestPostProcessor postProcessor):请求的后处理器,用于自定义一些请求处理的扩展点;
MockMultipartHttpServletRequestBuilder:
MockMultipartHttpServletRequestBuilder继承自MockHttpServletRequestBuilder,又提供了如下API:
MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上传的文件;
ResultActions:
调用MockMvc.perform(RequestBuilder requestBuilder)后将得到ResultActions,通过ResultActions完成如下三件事:
-
ResultActions andExpect(ResultMatcher matcher) :添加验证断言来判断执行请求后的结果是否是预期的;
-
ResultActions andDo(ResultHandler
handler) :添加结果处理器,用于对验证成功后执行的动作,如输出下请求/结果信息用于调试;
-
MvcResult andReturn() :返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;
ResultMatcher/MockMvcResultMatchers:
ResultMatcher用来匹配执行完请求后的结果验证,其就一个match(MvcResult result)断言方法,如果匹配失败将抛出相应的异常;此类案例中并为使用,请自行查看。具体提供以下API:
-
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)/ResultMatcher jsonPath(
String expression, Matcher matcher):得到
Json表达式验证器;
-
XpathResultMatchers xpath(
String expression, Object... args)/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);