MockMvc是服务端 Spring MVC测试支持的主入口点。可以用来模拟客户端请求,用于测试。
指定测试运行器,例如使用 SpringJUnit4ClassRunner.class
注意:如果使用的Spring的版本是4,则需要Servlet3的支持。
如果引入了低版本的Servlet,则会报错:
java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig
高版本Servlet Maven仓库链接
执行要加载的配置文件,例如 classpath:application.xml 或 file:src/main/resources/DispatcherServlet-servlet.xml
用于声明测试时所加载的是WebApplicationContext【WebMVC的 XmlWebApplicationContext 是其实现类】
因为测试需要使用WebMVC对应的IOC容器对象
注意它需要结合 @ContextConfiguration注解 一起使用,否则报错:
java.lang.IllegalStateException: Failed to load ApplicationContext
WebMVC的IOC容器对象,需要声明并通过@Autowired自动装配进来
用于构建MockHttpServletRequestBuilder
① get GET请求
② post POST请求
③ put PUT请求
④ delete DELETE请求
⑤ param(String name, String… values) 传递参数 K-V…
用于构建 MockHttpServletRequest,它用于作为 MockMvc的请求对象
通过 MockMvcBuilders 的 webAppContextSetup(WebApplicationContext context) 方法 获取 DefaultMockMvcBuilder,
再调用 build() 方法,初始化 MockMvc
perform(RequestBuilder requestBuilder) throws Exception
执行请求,需要传入 MockHttpServletRequest 对象【请求对象】
andDo(ResultHandler handler) throws Exception
执行普通处理,例如 MockMvcResultHandlers的print() 方法用于 打印请求、响应及其他相关信息
andExpect(ResultMatcher matcher) throws Exception
执行预期匹配,例如:
注意:当有一项不满足时,则后续就不会进行。
andReturn()
返回 MvcResult [请求访问结果]对象
getRequest()
返回 MockHttpServletRequest [请求]对象
public class MockHttpServletRequest implements HttpServletRequest { }
请求对象
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:application.xml", "file:src/main/resources/DispatcherServlet-servlet.xml"})
@WebAppConfiguration
// @Transactional 用于自动回滚操作
public class ???ControllerTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void initMockMvc() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testGetUsers() {
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/???")
.param("???", "???")
.param("???", "???");
try {
MockHttpServletRequest request = mockMvc.perform(requestBuilder)
.andDo(MockMvcResultHandlers.print()) // 打印请求、响应及其他相关信息
.andExpect(MockMvcResultMatchers.status().isOk()) // 期待返回的状态是OK【200】
.andExpect(MockMvcResultMatchers.content().string("hello")) // 期待返回的内容是“hello”
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_VALUE)) // 预期返回的媒体类型是JSON
.andExpect(MockMvcResultMatchers.forwardedUrl("/WEB-INF/views/result.jsp")) // 预期请求到此页面
.andReturn()
.getRequest();
// 拿到了请求对象。。。
} catch (Exception e) {
e.printStackTrace();
}
}
}
Tips:
可以在测试类上,添加 @Transactional 注解,用于自动回滚操作
添加此注解后,在执行完业务操作后,通过日志可以查看回滚操作:
DEBUG org.springframework.test.context.transaction.TransactionalTestExecutionListener.isRollback(TransactionalTestExecutionListener.java:429) No method-level @Rollback override: using default rollback [true] for test context [DefaultTestContext@???????? testClass = ???, testInstance = ???@????????, testMethod = ???@???, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@???????? testClass = ???, locations = '{???.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
DEBUG org.mybatis.spring.SqlSessionUtils$SqlSessionSynchronization.beforeCompletion(SqlSessionUtils.java:310) Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@????????]
DEBUG org.mybatis.spring.SqlSessionUtils$SqlSessionSynchronization.beforeCompletion(SqlSessionUtils.java:315) Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@????????]
DEBUG org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:847) Initiating transaction rollback
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager.doRollback(DataSourceTransactionManager.java:281) Rolling back JDBC transaction on Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@???????? [wrapping: com.mysql.jdbc.JDBC4Connection@????????]]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager.doCleanupAfterCompletion(DataSourceTransactionManager.java:324) Releasing JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@???????? [wrapping: com.mysql.jdbc.JDBC4Connection@????????]] after transaction
DEBUG org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:327) Returning JDBC Connection to DataSource
INFO org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:298) Rolled back transaction after test execution for test context [DefaultTestContext@???????? testClass = ???, testInstance = ???@????????, testMethod = ???@???, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@???????? testClass = ???, locations = '{???.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]