SpringMVC Mock测试实现原理及实现过程详解
什么是mock测试?
在测试过程中,对于某些不容易构成或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法,就是Mock测试。
Servlet、Request、Response等ServletAPI相关对象本来就是由Servlet容器(Tomcat)创建的。
这个虚拟的对象就是Mock对象。
Mock对象是真实对象在调试期间的代替品。
为什么使用Mock测试?
- 避免开发模块之间的耦合
- 轻量、简单、灵活
MockMVC介绍
MockMvcBuilder
他是用来构造MockMVC的构造器
主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder,分别对应之前的两种测试方式。
我们直接使用静态工厂MockMvcBuilders创建即可。
MockMvcBuilders
负责创建MockMvcBuilder对象
有两种创建方式
1、standaloneSetup(Object...controllers)
2、webAppContextSetup(WebApplicationContextwac):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc
MockMvc
对于服务器端的SpringMVC测试支持主入口点。
通过MockMvcBuilder构造
MockMvcBuilder由MockMvcBuilders的静态方法去构造。
核心方法:perform(RequestBuilderrequestBuilder)---->执行一个RequestBuilder请求,会自动执行SpringMvc的流程并映射到相应的控制器执行处理,该方法的返回值是一个ResultActions;
ResultActions
andExpect
添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确。
andDo
添加ResultHandler结果处理器,比如调试时打印结果到控制台;
andReturn
最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理。
MockMvcRequestBuilders
- 用来构造请求
- 主要由两个子类MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(如文件上传),即用来Mock客户端请求需要的所有数据。
MockMvcResultMatchers
- 用来匹配执行完请求后的结果验证
- 如果匹配失败将抛出相应的异常
- 包含了很多验证API方法
MockMvcResultHandlers
- 结果处理器,表示要对结果做点什么事情
- 比如此处使用MockMvcResultHandlers.print()输出整个相应结果信息。
MvcResult
单元测试执行结果,可以针对执行结果进行自定义验证逻辑。
MocMvc的使用
添加依赖
org.springframework spring-test 5.0.7.RELEASE junit junit 4.12
测试类
TestMockMVC.java
packagecom.cyb.ssm.controller.test;
importorg.junit.Before;
importorg.junit.Test;
importorg.junit.runner.RunWith;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.test.context.ContextConfiguration;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
importorg.springframework.test.context.web.WebAppConfiguration;
importorg.springframework.test.web.servlet.MockMvc;
importorg.springframework.test.web.servlet.MvcResult;
importorg.springframework.test.web.servlet.ResultActions;
importorg.springframework.test.web.servlet.request.MockMvcRequestBuilders;
importorg.springframework.test.web.servlet.result.MockMvcResultHandlers;
importorg.springframework.test.web.servlet.result.MockMvcResultMatchers;
importorg.springframework.test.web.servlet.setup.MockMvcBuilders;
importorg.springframework.web.context.WebApplicationContext;
//@WebAppConfiguration:可以在单元测试的时候,不用启动Servlet容器,就可以获取一个Web应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/*.xml")
@WebAppConfiguration
publicclassTestMockMVC{
@Autowired
privateWebApplicationContextwac;
privateMockMvcmockMvc;
@Before
publicvoidSetup(){
//初始化一个MockMVC对象的方式有两种:单独设置、web应用上下文设置
//建议使用web应用上下文设置
mockMvc=newMockMvcBuilders().webAppContextSetup(wac).build();
}
@Test
publicvoidtest()throwsException{
//通过perform去执行一个Http请求
//andExpect:通过该方法,判断请求执行是否成功
//andDo:对请求之后的结果,进行输出
MvcResultresult=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());
}
}
运行结果如下
JREOracleCorporation/13.0.1isnotsupported,advancedsourcelookupdisabled.
12月12,20194:48:43下午org.springframework.test.context.support.AbstractTestContextBootstrappergetDefaultTestExecutionListenerClassNames
信息:LoadeddefaultTestExecutionListenerclassnamesfromlocation[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,20194:48:43下午org.springframework.test.context.support.AbstractTestContextBootstrappergetTestExecutionListeners
信息:UsingTestExecutionListeners:[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,20194:48:43下午org.springframework.beans.factory.xml.XmlBeanDefinitionReaderloadBeanDefinitions
信息:LoadingXMLbeandefinitionsfromfile[D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\applicationContext-dao.xml]
12月12,20194:48:43下午org.springframework.beans.factory.xml.XmlBeanDefinitionReaderloadBeanDefinitions
信息:LoadingXMLbeandefinitionsfromfile[D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\applicationContext-service.xml]
12月12,20194:48:43下午org.springframework.beans.factory.xml.XmlBeanDefinitionReaderloadBeanDefinitions
信息:LoadingXMLbeandefinitionsfromfile[D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\applicationContext-tx.xml]
12月12,20194:48:43下午org.springframework.beans.factory.xml.XmlBeanDefinitionReaderloadBeanDefinitions
信息:LoadingXMLbeandefinitionsfromfile[D:\JAVA\eclipse_setup\ssm-project\target\classes\spring\springmvc.xml]
12月12,20194:48:43下午org.springframework.context.support.AbstractApplicationContextprepareRefresh
信息:Refreshingorg.springframework.web.context.support.GenericWebApplicationContext@50ad3bc1:startupdate[ThuDec1216:48:43CST2019];rootofcontexthierarchy
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/updateItem],produces=[application/json;charset=utf8]}"ontopubliccom.cyb.ssm.po.Itemcom.cyb.ssm.controller.ItemController.updateItem(java.lang.Integer,java.lang.String,java.lang.Float,com.cyb.ssm.po.Item,org.springframework.web.multipart.MultipartFile)throwsjava.lang.Exception
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/testRedirect],produces=[application/json;charset=utf8]}"ontopublicjava.lang.Stringcom.cyb.ssm.controller.ItemController.testRedirect(javax.servlet.http.HttpServletRequest)
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/testForward],produces=[application/json;charset=utf8]}"ontopublicjava.lang.Stringcom.cyb.ssm.controller.ItemController.testForward(javax.servlet.http.HttpServletRequest)
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/findItem],produces=[application/json;charset=utf8]}"ontopublicjava.lang.Stringcom.cyb.ssm.controller.ItemController.findItem(java.lang.Integer)
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/queryItem],produces=[application/json;charset=utf8]}"ontopublicorg.springframework.web.servlet.ModelAndViewcom.cyb.ssm.controller.ItemController.queryItem()throwscom.cyb.ssm.exception.CustomException
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/queryItem2],produces=[application/json;charset=utf8]}"ontopubliccom.cyb.ssm.po.Itemcom.cyb.ssm.controller.ItemController.queryItem2(com.cyb.ssm.po.ItemQueryVO)
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/deleteItem],produces=[application/json;charset=utf8]}"ontopublicvoidcom.cyb.ssm.controller.ItemController.deleteItem(java.lang.String[])
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/saveItem],produces=[application/json;charset=utf8]}"ontopublicjava.util.Datecom.cyb.ssm.controller.ItemController.saveItem(java.util.Date)
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/showEdit],produces=[application/json;charset=utf8]}"ontopublicorg.springframework.web.servlet.ModelAndViewcom.cyb.ssm.controller.ItemController.showEdit(java.lang.Integer)
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/item/batchUpdateItem],produces=[application/json;charset=utf8]}"ontopublicjava.util.Listcom.cyb.ssm.controller.ItemController.batchUpdateItem(com.cyb.ssm.po.ItemQueryVO)
12月12,20194:48:44下午org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistryregister
信息:Mapped"{[/queryItemByIdWithRest]}"ontopubliccom.cyb.ssm.po.Itemcom.cyb.ssm.controller.RestItemController.queryItemById()
12月12,20194:48:44下午org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapterinitControllerAdviceCache
信息:Lookingfor@ControllerAdvice:org.springframework.web.context.support.GenericWebApplicationContext@50ad3bc1:startupdate[ThuDec1216:48:43CST2019];rootofcontexthierarchy
12月12,20194:48:44下午org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapterinitControllerAdviceCache
信息:Lookingfor@ControllerAdvice:org.springframework.web.context.support.GenericWebApplicationContext@50ad3bc1:startupdate[ThuDec1216:48:43CST2019];rootofcontexthierarchy
12月12,20194:48:44下午org.springframework.mock.web.MockServletContextlog
信息:InitializingSpringFrameworkServlet''
12月12,20194:48:44下午org.springframework.web.servlet.FrameworkServletinitServletBean
信息:FrameworkServlet'':initializationstarted
12月12,20194:48:44下午org.springframework.web.servlet.FrameworkServletinitServletBean
信息:FrameworkServlet'':initializationcompletedin17ms
com.cyb.ssm.po.Item@1ad9b8d3
MockHttpServletRequest:
HTTPMethod=GET
RequestURI=/item/showEdit
Parameters={id=[1]}
Headers={}
Body=
SessionAttrs={}
Handler:
Type=com.cyb.ssm.controller.ItemController
Method=publicorg.springframework.web.servlet.ModelAndViewcom.cyb.ssm.controller.ItemController.showEdit(java.lang.Integer)
Async:
Asyncstarted=false
Asyncresult=null
ResolvedException:
Type=null
ModelAndView:
Viewname=item/item-edit
View=null
Attribute=item
value=com.cyb.ssm.po.Item@1ad9b8d3
errors=[]
FlashMap:
Attributes=null
MockHttpServletResponse:
Status=200
Errormessage=null
Headers={Content-Language=[en]}
Contenttype=null
Body=
ForwardedURL=/WEB-INF/jsp/item/item-edit.jsp
RedirectedURL=null
Cookies=[]
===============
publicorg.springframework.web.servlet.ModelAndViewcom.cyb.ssm.controller.ItemController.showEdit(java.lang.Integer)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。