1. 概述
对模块进行集成测试时,希望能够通过输入URL
对controller
进行测试,如果通过启动服务器,建立http client
进行测试,这样会使得测试的变得的很麻烦,比如: 启动速度慢、测试验证不方便、依赖网络环境等,这样会导致测试无法进行,为了可以对Controller
进行测试,可以通过引入MockMVC
进行解决.
2.运行配置
-
引入的jar :
<!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!-- spring test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.5.RELEASE</version> </dependency>
-
用到的注解 :
1.
@RunWith(SpringJunit4ClassRunner.class)
: 表示使用Spring Test
组件进行单元测试 .2.
@WebAppConfiguration
: 使用这个Annotaion
会在跑单元测试时真实的启动一个web
服务,然后开始调用Controller
的Restful API
,待单元测试跑完之后再将web
服务停掉.3.
@ContextConfiguration({ "classpath:spring-mvc.xml", "classpath:applicationContext.xml"})
: 指定Bean
的配置文件信息,可以有多种方式,这个例子使用的文件路径形式,如果有多个配置文件,可以将括号中的信息配置为一个字符串数组来表示.
3. 基本框架
**测试 : **
package com.makesailing.neo;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({ "classpath:spring-mvc.xml", "classpath:applicationContext.xml"})
public class BaseControllerTest {
// 注入web环境的ApplicationContext容器
@Autowired
protected WebApplicationContext webApplicationContext;
/**
* 模拟mvc测试对象
*/
protected MockMvc mockMvc;
/**
* 所有测试方法执行之前执行该方法
*/
@Before // 这个注解的作用,在每个方法之前都会执行一遍
public void before() {
//获取mockmvc对象实例
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
// 配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
public class UserControllerTest extends BaseControllerTest {
/**
* Method: getUserDetailById(@PathVariable(name = "id") Long id)
*/
@Test
public void testGetUserDetailById() throws Exception {
RequestBuilder request = null;
request = get('v1/user/{id}/detail", 1);
String responseString = mockMvc.perform(request)
.andExpect(status().isOk()) // 返回的状态是200
.andDo(print()) // 打印出请求和相应的内容
.andReturn().getResponse().getContentAsString(); // 将数据转换为字符串
Assert.assertNotNull(responseString);
System.out.println(responseString);
}
}
Controller层 :
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("v1/user/{id}/detail")
public String getUserDetailById(@PathVariable(name = "id") Long id) {
User user = userService.getUserDetailById(id);
return JSON.toJSONString(user);
}
}
代码解析 :
perform
:执行一个RequestBuider
请求,自动执行SpringMvc
的流程并映射到相应的控制器执行处理get
: 声明一个发送get
请求的方法.public static MockHttpServletRequestBuilder get(String urlTemplate, Object... uriVars) { return new MockHttpServletRequestBuilder(HttpMethod.GET, urlTemplate, uriVars);}
这是个静态方法,可以直接导入,根据uri模版和uri的变量值得到一个get
请求的方法. 另外提供了其他的请求方法, 如:post
、put
、delete
等.andExperct
: 添加ResultMatcher
验证规则,验证perform
执行完成后的结果是否正确(对返回的数据进行判断)andDo
: 添加ResultHandler
结果处理器,比如调试打印结果到控制台print()
andReturn
: 最后返回相应的MvcResult
,然后进行自定义验证/进行下一步的异步处理.
注意如果是post
、put
测试,Controller
使用@RequestBody User user
进行接收,那么测试时也需要使用json
格式数据,如下 :
/**
* Method: saveUser(@RequestBody User user)
*/
@Test
public void testSaveUser() throws Exception {
User user = new User();
user.setEmail("12345678@qq.com");
user.setUsername("jack");
user.setPassword("123456");
user.setRole("root");
user.setStatus(1);
user.setRegtime(new Date());
//user.setRegip("127.0.0.1");
String content = JSON.toJSONString(user);
String response = mockMvc.perform(
post(Urls.User.SAVE_USER).contentType(MediaType.APPLICATION_JSON_UTF8).content(content))
.andDo(print())
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
Assert.assertNotNull(response);
Assert.assertNotEquals(response,"");
System.out.println(response);
}
/**
* Method: updateUser(@RequestBody User user)
*/
@Test
public void testUpdateUser() throws Exception {
User user = new User();
user.setId(2L);
user.setUsername("tom");
String respone = mockMvc.perform(
put(Urls.User.UPDATE_USER).contentType(MediaType.APPLICATION_JSON_UTF8).content(JSON.toJSONString(user)))
.andDo(print()).andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
Assert.assertNotNull(respone);
System.out.println(respone);
}
4 .RequestBuilder/MockMvcRequestBuilders 相关API详细描述
RequestBuilder/MockMvcRequestBuilders
从名字可以看出,RequestBuilder用来构建请求的,其提供了一个方法buildRequest(ServletContext servletContext)用于构建MockHttpServletRequest;其主要有两个子类MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(如文件上传使用),即用来Mock客户端请求需要的所有数据.
4.1 .MockMvcRequestBuilders主要API
MockHttpServletRequestBuilder get(String urlTemplate, Object… urlVariables):根据uri模板和uri变量值得到一个GET请求方式的MockHttpServletRequestBuilder;如get(/user/{id}, 1L);
- MockHttpServletRequestBuilder post(String urlTemplate, Object… urlVariables):同get类似,但是是POST方法;
- 提供自己的Http请求方法及uri模板和uri变量,如上API都是委托给这个API;
- MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object… urlVariables):提供文件上传方式的请求,得MockMultipartHttpServletRequestBuilder;
- RequestBuilder asyncDispatch(final MvcResult mvcResult):创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder;
- MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder API
- 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 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):请求的后处理器,用于自定义一些请求处理的扩展点;
4.2 MockMultipartHttpServletRequestBuilder 主要API
- MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上传的文件;
4.3 ResultActions
调用MockMvc.perform(RequestBuilder requestBuilder)后将得到ResultActions,通过ResultActions完成如下三件事:
- ResultActions andExpect(ResultMatcher matcher) :添加验证断言来判断执行请求后的结果是否是预期的;
- ResultActions andDo(ResultHandler handler) :添加结果处理器,用于对验证成功后执行的动作,如输出下请求/结果信息用于调试;
- MvcResult andReturn() :返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;
- **ResultMatcher/MockMvcResultMatchers **
ResultMatcher用来匹配执行完请求后的结果验证,其就一个match(MvcResult result)断言方法,如果匹配失败将抛出相应的异常;spring mvc测试框架提供了很多***ResultMatchers来满足测试需求。注意这些***ResultMatchers并不是ResultMatcher的子类,而是返回ResultMatcher实例的。Spring mvc测试框架为了测试方便提供了MockMvcResultMatchers静态工厂方法方便操作;
具体的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)