1、概念

MockMvc是服务端 Spring MVC测试支持的主入口点。可以用来模拟客户端请求,用于测试。

2、API

⑴ @RunWith注解

指定测试运行器,例如使用 SpringJUnit4ClassRunner.class

注意:如果使用的Spring的版本是4,则需要Servlet3的支持。
如果引入了低版本的Servlet,则会报错:
java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig
高版本Servlet Maven仓库链接

⑵ @ContextConfiguration注解

执行要加载的配置文件,例如 classpath:application.xml 或 file:src/main/resources/DispatcherServlet-servlet.xml

⑶ @WebAppConfiguration注解

用于声明测试时所加载的是WebApplicationContext【WebMVC的 XmlWebApplicationContext 是其实现类】
因为测试需要使用WebMVC对应的IOC容器对象

注意它需要结合 @ContextConfiguration注解 一起使用,否则报错:
java.lang.IllegalStateException: Failed to load ApplicationContext

⑷ WebApplicationContext

WebMVC的IOC容器对象,需要声明并通过@Autowired自动装配进来

⑸ MockMvcRequestBuilders

用于构建MockHttpServletRequestBuilder

① get GET请求
② post POST请求
③ put PUT请求
④ delete DELETE请求
⑤ param(String name, String… values) 传递参数 K-V…

⑹ MockHttpServletRequestBuilder

用于构建 MockHttpServletRequest,它用于作为 MockMvc的请求对象

⑺ MockMvc

通过 MockMvcBuilders 的 webAppContextSetup(WebApplicationContext context) 方法 获取 DefaultMockMvcBuilder,
再调用 build() 方法,初始化 MockMvc

① perform

perform(RequestBuilder requestBuilder) throws Exception
执行请求,需要传入 MockHttpServletRequest 对象【请求对象】

② andDo

andDo(ResultHandler handler) throws Exception
执行普通处理,例如 MockMvcResultHandlers的print() 方法用于 打印请求、响应及其他相关信息

③ andExpect

andExpect(ResultMatcher matcher) throws Exception
执行预期匹配,例如:

  1. MockMvcResultMatchers.status().isOk() 预期响应成功
  2. MockMvcResultMatchers.content().string(final String expectedContent) 指定预期的返回结果内容[字符串]
  3. MockMvcResultMatchers.content().contentType(String contentType) 指定预期的返回结果的媒体类型
  4. MockMvcResultMatchers.forwardedUrl(final String expectedUrl) 指定预期的请求的URL链接
  5. MockMvcResultMathcers.redirectedUrl(final String expectedUrl) 指定预期的重定向的URL链接

注意:当有一项不满足时,则后续就不会进行。

④ andReturn

andReturn()
返回 MvcResult [请求访问结果]对象

⑤ getRequest

getRequest()
返回 MockHttpServletRequest [请求]对象

⑻ MockHttpServletRequest

public class MockHttpServletRequest implements HttpServletRequest { }

请求对象

3、示例

@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]]]
  1. 准备回滚操作
  2. 事务同步注销SqlSession
  3. 事务同步关闭SqlSession
  4. 初始化事务回滚操作
  5. 回滚对应的JDBC连接的事务操作
  6. 释放JDBC连接
  7. 将JDBC连接放回数据源连接池中
  8. 结束事务操作
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐