SpringMVC Mock测试实现原理及实现过程详解

 更新时间:2020年10月09日 10:41:43   作者:陈彦斌  
这篇文章主要介绍了SpringMVC Mock测试实现原理及实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

什么是mock测试?

  在测试过程中,对于某些不容易构成或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法,就是Mock测试。

  Servlet、Request、Response等Servlet API相关对象本来就是由Servlet容器(Tomcat)创建的。

  这个虚拟的对象就是Mock对象。

  Mock对象是真实对象在调试期间的代替品。

为什么使用Mock测试?

  • 避免开发模块之间的耦合
  • 轻量、简单、灵活

MockMVC介绍

MockMvcBuilder

  他是用来构造MockMVC的构造器

  主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,分别对应之前的两种测试方式。

  我们直接使用静态工厂MockMvcBuilders创建即可。

MockMvcBuilders

  负责创建MockMvcBuilder对象

  有两种创建方式

    1、standaloneSetup(Object... controllers)

    2、webAppContextSetup(WebApplicationContext wac):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc

MockMvc

  对于服务器端的Spring MVC测试支持主入口点。

  通过MockMvcBuilder构造

  MockMvcBuilder由MockMvcBuilders的静态方法去构造。

  核心方法:perform(RequestBuilder requestBuilder)---->执行一个RequestBuilder请求,会自动执行SpringMvc的流程并映射到相应的控制器执行处理,该方法的返回值是一个ResultActions;

ResultActions

andExpect

  添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确。

andDo

  添加ResultHandler结果处理器,比如调试时打印结果到控制台;

andReturn

  最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理。

MockMvcRequestBuilders

  • 用来构造请求
  • 主要由两个子类MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(如文件上传),即用来Mock客户端请求需要的所有数据。

MockMvcResultMatchers

  • 用来匹配执行完请求后的结果验证
  • 如果匹配失败将抛出相应的异常
  • 包含了很多验证API方法

MockMvcResultHandlers

  • 结果处理器,表示要对结果做点什么事情
  • 比如此处使用MockMvcResultHandlers.print()输出整个相应结果信息。

MvcResult

  单元测试执行结果,可以针对执行结果进行自定义验证逻辑。

MocMvc的使用

添加依赖

    <!-- spring 单元测试组件包 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.7.RELEASE</version>
    </dependency>
 
    <!-- 单元测试Junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>

测试类

TestMockMVC.java

package com.cyb.ssm.controller.test;

import org.junit.Before;
import org.junit.Test;
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.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

//@WebAppConfiguration:可以在单元测试的时候,不用启动Servlet容器,就可以获取一个Web应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/*.xml")
@WebAppConfiguration
public class TestMockMVC {
  @Autowired
  private WebApplicationContext wac;
  private MockMvc mockMvc;

  @Before
  public void Setup() {
    // 初始化一个MockMVC对象的方式有两种:单独设置、web应用上下文设置
    // 建议使用web应用上下文设置
    mockMvc = new MockMvcBuilders().webAppContextSetup(wac).build();
  }

  @Test
  public void test() throws Exception {
    // 通过perform去执行一个Http请求
    // andExpect:通过该方法,判断请求执行是否成功
    // andDo:对请求之后的结果,进行输出
    MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/item/showEdit").param("id", "1"))
        .andExpect(MockMvcResultMatchers.view().name("item/item-edit"))
        .andExpect(MockMvcResultMatchers.status().isOk())
        .andDo(MockMvcResultHandlers.print())
        .andReturn();
    System.out.println("===============");
    System.out.println(result.getHandler());
  }
}

运行结果如下

JRE Oracle Corporation/13.0.1 is not supported, advanced source lookup disabled.
12月 12, 2019 4:48:43 下午 org.springframework.test.context.support.AbstractTestContextBootstrapper getDefaultTestExecutionListenerClassNames
信息: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
12月 12, 2019 4:48:43 下午 org.springframework.test.context.support.AbstractTestContextBootstrapper getTestExecutionListeners
信息: Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@4470f8a6, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@7c83dc97, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@7748410a, org.springframework.test.context.support.DirtiesContextTestExecutionListener@740773a3, org.springframework.test.context.transaction.TransactionalTestExecutionListener@37f1104d, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@55740540]
12月 12, 2019 4:48:43 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\applicationContext-dao.xml]
12月 12, 2019 4:48:43 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\applicationContext-service.xml]
12月 12, 2019 4:48:43 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\applicationContext-tx.xml]
12月 12, 2019 4:48:43 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\springmvc.xml]
12月 12, 2019 4:48:43 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.web.context.support.GenericWebApplicationContext@50ad3bc1: startup date [Thu Dec 12 16:48:43 CST 2019]; root of context hierarchy
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/updateItem],produces=[application/json;charset=utf8]}" onto public com.cyb.ssm.po.Item com.cyb.ssm.controller.ItemController.updateItem(java.lang.Integer,java.lang.String,java.lang.Float,com.cyb.ssm.po.Item,org.springframework.web.multipart.MultipartFile) throws java.lang.Exception
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/testRedirect],produces=[application/json;charset=utf8]}" onto public java.lang.String com.cyb.ssm.controller.ItemController.testRedirect(javax.servlet.http.HttpServletRequest)
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/testForward],produces=[application/json;charset=utf8]}" onto public java.lang.String com.cyb.ssm.controller.ItemController.testForward(javax.servlet.http.HttpServletRequest)
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/findItem],produces=[application/json;charset=utf8]}" onto public java.lang.String com.cyb.ssm.controller.ItemController.findItem(java.lang.Integer)
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/queryItem],produces=[application/json;charset=utf8]}" onto public org.springframework.web.servlet.ModelAndView com.cyb.ssm.controller.ItemController.queryItem() throws com.cyb.ssm.exception.CustomException
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/queryItem2],produces=[application/json;charset=utf8]}" onto public com.cyb.ssm.po.Item com.cyb.ssm.controller.ItemController.queryItem2(com.cyb.ssm.po.ItemQueryVO)
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/deleteItem],produces=[application/json;charset=utf8]}" onto public void com.cyb.ssm.controller.ItemController.deleteItem(java.lang.String[])
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/saveItem],produces=[application/json;charset=utf8]}" onto public java.util.Date com.cyb.ssm.controller.ItemController.saveItem(java.util.Date)
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/showEdit],produces=[application/json;charset=utf8]}" onto public org.springframework.web.servlet.ModelAndView com.cyb.ssm.controller.ItemController.showEdit(java.lang.Integer)
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/item/batchUpdateItem],produces=[application/json;charset=utf8]}" onto public java.util.List<com.cyb.ssm.po.Item> com.cyb.ssm.controller.ItemController.batchUpdateItem(com.cyb.ssm.po.ItemQueryVO)
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry register
信息: Mapped "{[/queryItemByIdWithRest]}" onto public com.cyb.ssm.po.Item com.cyb.ssm.controller.RestItemController.queryItemById()
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
信息: Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@50ad3bc1: startup date [Thu Dec 12 16:48:43 CST 2019]; root of context hierarchy
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
信息: Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@50ad3bc1: startup date [Thu Dec 12 16:48:43 CST 2019]; root of context hierarchy
12月 12, 2019 4:48:44 下午 org.springframework.mock.web.MockServletContext log
信息: Initializing Spring FrameworkServlet ''
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.FrameworkServlet initServletBean
信息: FrameworkServlet '': initialization started
12月 12, 2019 4:48:44 下午 org.springframework.web.servlet.FrameworkServlet initServletBean
信息: FrameworkServlet '': initialization completed in 17 ms
com.cyb.ssm.po.Item@1ad9b8d3

MockHttpServletRequest:
HTTP Method = GET
Request URI = /item/showEdit
Parameters = {id=[1]}
Headers = {}
Body = <no character encoding set>
Session Attrs = {}

Handler:
Type = com.cyb.ssm.controller.ItemController
Method = public org.springframework.web.servlet.ModelAndView com.cyb.ssm.controller.ItemController.showEdit(java.lang.Integer)

Async:
Async started = false
Async result = null

Resolved Exception:
Type = null

ModelAndView:
View name = item/item-edit
View = null
Attribute = item
value = com.cyb.ssm.po.Item@1ad9b8d3
errors = []

FlashMap:
Attributes = null

MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Language=[en]}
Content type = null
Body =
Forwarded URL = /WEB-INF/jsp/item/item-edit.jsp
Redirected URL = null
Cookies = []
===============
public org.springframework.web.servlet.ModelAndView com.cyb.ssm.controller.ItemController.showEdit(java.lang.Integer)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 本真的REST架构风格理解

    本真的REST架构风格理解

    这篇文章主要为大家介绍了本真的REST架构风格的深入理解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • 关于Swagger注释API的使用说明

    关于Swagger注释API的使用说明

    这篇文章主要介绍了关于Swagger注释API的使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Java编程中void方法的学习教程

    Java编程中void方法的学习教程

    这篇文章主要介绍了Java编程中void方法的学习教程,包括对void方法进行单元测试,需要的朋友可以参考下
    2015-10-10
  • 基于Java中throw和throws的区别(详解)

    基于Java中throw和throws的区别(详解)

    下面小编就为大家带来一篇基于Java中throw和throws的区别(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Java 数据结构与算法系列精讲之字符串暴力匹配

    Java 数据结构与算法系列精讲之字符串暴力匹配

    字符串暴力匹配算法是指在一个长字符串中暴力寻找是否包含某一子串所谓暴力匹配,就是不使用任何其他算法,将两个字符串中的字符一一进行比对
    2022-02-02
  • SpringBoot之使用Feign实现微服务间的交互

    SpringBoot之使用Feign实现微服务间的交互

    这篇文章主要介绍了SpringBoot中使用Feign实现微服务间的交互,对微服务这方面感兴趣的小伙伴可以参考阅读本文
    2023-03-03
  • Java中使用RediSearch实现高效的数据检索功能

    Java中使用RediSearch实现高效的数据检索功能

    RediSearch是一款构建在Redis上的搜索引擎,它为Redis数据库提供了全文搜索、排序、过滤和聚合等高级查询功能,本文将介绍如何在Java应用中集成并使用RediSearch,以实现高效的数据检索功能,感兴趣的朋友跟着小编一起来看看吧
    2024-05-05
  • Java中的什么场景使用递归,如何使用递归

    Java中的什么场景使用递归,如何使用递归

    这篇文章主要介绍了Java中的什么场景使用递归,如何使用递归的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • java随机生成字符串(字符随机生成类 生成随机字符组合)

    java随机生成字符串(字符随机生成类 生成随机字符组合)

    java随机生成字符串,字符组合多样,可以大小字组合、大+小字符+数字等方式,大家参考使用吧
    2013-12-12
  • Java死锁的产生原因及解决方法总结

    Java死锁的产生原因及解决方法总结

    Java中的死锁是指多个线程同时占用一些共享资源且彼此相互等待,从而导致所有的线程都被阻塞,不能继续执行程序的情况,本文小编给大家介绍了Java死锁的产生原因及解决方法总结,需要的朋友可以参考下
    2023-11-11

最新评论