使用MockMvc测试Controller

1. 概述

对模块进行集成测试时,希望能够通过输入URLcontroller进行测试,如果通过启动服务器,建立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服务,然后开始调用ControllerRestful 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请求的方法. 另外提供了其他的请求方法, 如:postputdelete 等.
  • andExperct: 添加ResultMatcher验证规则,验证perform执行完成后的结果是否正确(对返回的数据进行判断)
  • andDo: 添加ResultHandler结果处理器,比如调试打印结果到控制台print()
  • andReturn: 最后返回相应的MvcResult,然后进行自定义验证/进行下一步的异步处理.

注意如果是postput 测试,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)
  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值