欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot单元测试(二)MockMVC

程序员文章站 2022-06-05 12:11:16
...

介绍

MockMvc,从字面来理解,很好理解,主要是用来模拟MVC。简单来说,就是模拟可以从客户端请求后端的Controller类。

样例:

1. 非自动注入式

TestApplicationTests类已经有@RunWith(SpringRunner.class)和@SpringBootTest注解了,具体参考上一篇文章

SpringBoot 单元测试(一)SpringBootTest

package com.orjrs.spring.test.unit;

import com.orjrs.spring.test.TestApplicationTests;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
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;

/**
 * MockMvcTest
 *
 * @author orjrs
 * @date 2018-10-06 20:15
 */
@WebAppConfiguration // 1
public class MockMvcTest extends TestApplicationTests {
    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @Before // @Test注解的方法运行前执行,MockMvcBuilder构造MockMvc实例
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void post() throws Exception {
        String name = "Smart LIU";
        String msg = "您好";
        mockMvc.perform(
                MockMvcRequestBuilders.post("/unit/sayHello/" + name + "/" + msg)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                //.content()
        )
                .andExpect(MockMvcResultMatchers.status().isOk())
                //.andExpect(MockMvcResultMatchers.content().contentType("text/plain;charset=UTF-8"))
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
    }
}

2. 自动注入
package com.orjrs.spring.test.unit;

import com.orjrs.spring.test.TestApplicationTests;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.http.MediaType;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
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;

/**
 * MockMvcTest
 *
 * @author orjrs
 * @date 2018-10-21 16:12
 */
@WebAppConfiguration // 1
@AutoConfigureMockMvc // 开启MockMvc自动注解
public class AutoMockMvcTest extends TestApplicationTests {
    // @Autowired
    // private WebApplicationContext webApplicationContext;

    @Autowired
    private MockMvc mockMvc;

    /*@Before // @Test注解的方法运行前执行,MockMvcBuilder构造MockMvc实例
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }*/

    @Test
    public void post() throws Exception {
        String name = "Smart LIU";
        String msg = "您好";
        mockMvc.perform(
                MockMvcRequestBuilders.post("/unit/sayHello/" + name + "/" + msg)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                //.content()
        )
                .andExpect(MockMvcResultMatchers.status().isOk())
                //.andExpect(MockMvcResultMatchers.content().contentType("text/plain;charset=UTF-8"))
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
    }
}

源码分析:

MockMvcBuilders: 主要是用来构造MockMvc的。它有两个方法,如下:

public class MockMvcBuilders {
    public MockMvcBuilders() {
    }
    // 通过指定WebApplicationContext,根据上下文获取相应的Controller来构建MockMvc
    public static DefaultMockMvcBuilder webAppContextSetup(WebApplicationContext context) {
        return new DefaultMockMvcBuilder(context);
    }
    // 通过参数直接指定一组控制器来构建MockMVC
    public static StandaloneMockMvcBuilder standaloneSetup(Object... controllers) {
        return new StandaloneMockMvcBuilder(controllers);
    }
}

AbstractMockMvcBuilder还实现了ConfigurableMockMvcBuilder接口,即有以下方法

package org.springframework.test.web.servlet.setup;

import javax.servlet.Filter;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultHandler;
import org.springframework.test.web.servlet.ResultMatcher;

public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder<B>> extends MockMvcBuilder {
    <T extends B> T addFilters(Filter... var1);// 添加过滤器

    <T extends B> T addFilter(Filter var1, String... var2);// 添加过滤器

    <T extends B> T defaultRequest(RequestBuilder var1);//默认的RequestBuilder,每次执行时会合并到自定义的RequestBuilder中,即提供公共请求数据的;

    <T extends B> T alwaysExpect(ResultMatcher var1); // 定义全局的结果验证器,即每次执行请求时都进行验证的规则;

    <T extends B> T alwaysDo(ResultHandler var1);// 定义全局结果处理器,即每次请求时都进行结果处理;

    <T extends B> T dispatchOptions(boolean var1); // DispatcherServlet是否分发OPTIONS请求方法到控制器;

    <T extends B> T apply(MockMvcConfigurer var1);
}
public interface MockMvcBuilder {
    MockMvc build();
}

StandaloneMockMvcBuilder除了继承AbstractMockMvcBuilder之外,自己还提供了许多方法,这里不多说了。

MockMvc:
mockMvc.perform(
                MockMvcRequestBuilders.post("/unit/sayHello/" + name + "/" + msg)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                //.content()
        )
                .andExpect(MockMvcResultMatchers.status().isOk())
                //.andExpect(MockMvcResultMatchers.content().contentType("text/plain;charset=UTF-8"))
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
    }

perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理,返回ResultActions类;

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

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

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

另外还提供了以下API:

setDefaultRequest:设置默认的RequestBuilder,用于在每次perform执行相应的RequestBuilder时自动把该默认的RequestBuilder合并到perform的RequestBuilder中;

setGlobalResultMatchers:设置全局的预期结果验证规则,如我们通过MockMvc测试多个控制器时,假设它们都想验证某个规则时,就可以使用这个;

setGlobalResultHandlers:设置全局的ResultHandler结果处理器;

RequestBuilder/MockMvcRequestBuilders

Request请求,有put、get、post、delete、patch、options、head、request、multipart、fileUpload、asyncDispatch请求方法。

MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder

主要是针对请求头的。有header、contentType、cookie、characterEncoding、requestAttr、sessionAttr、contextPath等方法