★  MockMvc - SpringMVC单元测试的独立测试:

一、简介

为何使用MockMvc?

        对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,所以为了可以对Controller进行测试,我们引入了MockMVC。

        MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。

二、 测试逻辑

  1.  MockMvcBuilder构造MockMvc的构造器
  2. perform,执行一个RequestBuilder请求,调用controller的业务处理逻辑
  3. ResultActions,返回操作结果,通过ResultActions,提供了统一的验证方式
  4. 使用StatusResultMatchers对请求结果进行验证
  5. 使用ContentResultMatchers对请求返回的内容进行验证

三、MockMvcBuilder

MockMvc是spring测试下的一个非常好用的类,他们的初始化需要在setUp中进行。

MockMvcBuilder是用来构造MockMvc的构造器,其主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,前者继承了后者。

① MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc;

② MockMvcBuilders.standaloneSetup(Object... controllers):通过参数指定一组控制器,这样就不需要从上下文获取了,比如this.mockMvc = MockMvcBuilders.standaloneSetup(this.controller).build();

这些Builder还提供了其他api,可以自行百度

四、MockMvcRequestBuilders

        从名字可以看出,RequestBuilder用来构建请求的,其提供了一个方法buildRequest(ServletContext servletContext)用于构建MockHttpServletRequest;其主要有两个子类MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(如文件上传使用),即用来Mock客户端请求需要的所有数据。

主要API:

  1. 如果在controller的方法中method选择的是RequestMethod.GET,那在controllerTest中对应就要使用MockMvcRequestBuilders.get。
  2. post(String urlTemplate, Object... urlVariables):同get类似,但是是POST方法;
  3. put(String urlTemplate, Object... urlVariables):同get类似,但是是PUT方法;
  4. delete(String urlTemplate, Object... urlVariables) :同get类似,但是是DELETE方法;
  5. options(String urlTemplate, Object... urlVariables):同get类似,但是是OPTIONS方法;

五、ResultActions

    调用MockMvc.perform(RequestBuilder requestBuilder)后将得到ResultActions,对ResultActions有以下三种处理:

  1. andExpect:添加执行完成后的断言。添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确;
  2. andDo:添加一个结果处理器,比如此处使用.andDo(MockMvcResultHandlers.print())输出整个响应结果信息,可以在调试的时候使用。(备注)
  3. andReturn:表示执行完成后返回相应的结果

备注:

    ResultHandler用于对处理的结果进行相应处理的,比如输出整个请求/响应等信息方便调试,Spring mvc测试框架提供了MockMvcResultHandlers静态工厂方法,该工厂提供了ResultHandler print()返回一个输出MvcResult详细信息到控制台的ResultHandler实现。

例子:

String example= "{\"id\":1, \"name\":\"kqzu\"}";  

mockMvc.perform(post("/user")  // 路径

            .contentType(MediaType.APPLICATION_JSON)   //用 contentType表示具体 请求中 的媒体类型信息,MediaType.APPLICATION_JSON表示互联网媒体类型的json数据格式(见备注)

            .content( example )  

            .accept(MediaType.APPLICATION_JSON)) // accept指定客户端能够接收的内容类型  

        .andExpect(content().contentType( "application/json;charset=UTF-8" )) //验证响应contentType == application/json;charset=UTF-8

        .andExpect(jsonPath("$.id").value(1))  //验证id是否为1,jsonPath的使用

kqzhu");  // 验证name是否等于Zhukeqian

String errorE xample = "{id:1, name:kqzhu}";  

MvcResult result = mockMvc.perform(post("/user")  

        .contentType(MediaType.APPLICATION_JSON).content( errorExample )  

        .accept(MediaType.APPLICATION_JSON)) //执行请求  

        .andExpect(status().isBadRequest()) //400错误请求,  status().isOk() 正确   status().isNotFound() 验证控制器不存在

        .andReturn();   //返回MvcResult

备注:使用Content-type来指定不同格式的请求信息,下面例举在日常的开发中,常会用的若干content-type的内容格式

    例如: Content-Type: text/html;charset:utf-8;

 常见的媒体格式类型如下:

  •     text/html : HTML格式
  •     text/plain :纯文本格式      
  •     text/xml :  XML格式 /
  •     image/gif :gif图片格式    
  •     image/jpeg :jpg图片格式 
  •     image/png:png图片格式

   以application开头的媒体格式类型:

  •    application/xhtml+xml :XHTML格式
  •    application/xml     : XML数据格式
  •    application/atom+xml  :Atom XML聚合格式    
  •    application/json    : JSON数据格式
  •    application/pdf       :pdf格式  
  •    application/msword  : Word文档格式
  •    application/octet-stream : 二进制流数据(如常见的文件下载)
  •    application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

   另外一种常见的媒体格式是上传文件之时使用的:

  •     multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

附录: Requests & Responses 的标识及解释 

六、ResultMatchers 

        ResultMatcher用来匹配执行完请求后的结果验证,其就一个match(MvcResult result)断言方法,如果匹配失败将抛出相应的异常,spring mvc测试框架提供了很多***ResultMatchers来满足测试需求。

具体请百度。

七、MvcResult

        即执行完控制器后得到的整个结果,并不仅仅是返回值,其包含了测试时需要的所有信息。

  • getRequest():得到执行的请求;
  • getResponse():得到执行后的响应;
  • Object getHandler():得到执行的处理器,一般就是控制器;
  • HandlerInterceptor[] getInterceptors():得到对处理器进行拦截的拦截器;
  • ModelAndView getModelAndView():得到执行后的ModelAndView;
  • Exception getResolvedException():得到HandlerExceptionResolver解析后的异常;
  • FlashMap getFlashMap():得到FlashMap;
  • Object getAsyncResult()/Object getAsyncResult(long timeout):得到异步执行的结果;

资料:史上最全, Spring MVC测试框架详解——服务端测试