1. 引入依赖

其实使用 Spring Quickstart 建立的项目都会自动引入

	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

2. 建 Test Class

image.png

/**
 * WebEnvironment:
 * DEFINED_PORT:创建一个(reactive) web 应用程序上下文,使用默认端口。针对这个属性,网上翻译的解读比较多,错误的也多。
 * MOCK:MOCK 是用的比较多的一个属性。它会判断,当你使用 servlet API 时,则使用模拟 servlet 环境创建 WebApplicationContext;如果是使用 WebFlux,则使用 ReactiveWebApplicationContext;否则,使用常规的 ApplicationContext。
 * NONE:这个也有很多人理解错误,其实它主要是表示,它不会指定 SpringApplication.setWebApplicationType。以非 Web 环境来运行。也就是非 Servlet 和 Reactive 环境。
 * RANDOM_PORT:创建一个 web 应用程序上下文,可以是 reactive,也可以是 servlet。它将随机起一个端口并监听。到底是 reactive 还是 Servlet,它会自己根据上下文来判断。
 */
@DisplayName("测试-用户登录信息")
@Slf4j
// 导入spring 测试框架
@ExtendWith(SpringExtension.class) 
@SpringBootTest(classes = {ApiApplication.class},SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS) // 配合 BeforeAll 等注解使用
@AutoConfigureMockMvc
public class UserInfoControllerTest {

    @Autowired
    private MockMvc mockMvc;

    private Gson gson;
    /**
     * 针对 gson 格式化 LocalDateTime
     */
    @BeforeAll
    public void create(){
         class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime> {
            @Override
            public JsonElement serialize(LocalDateTime localDateTime, Type type, JsonSerializationContext jsonSerializationContext) {
                return new JsonPrimitive(localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        }
        class LocalDateAdapter implements JsonSerializer<LocalDate> {
            @Override
            public JsonElement serialize(LocalDate localDate, Type type, JsonSerializationContext jsonSerializationContext) {
                return new JsonPrimitive(localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        }

        gson = new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapter(LocalDateTime.class,new LocalDateTimeAdapter())
                .registerTypeAdapter(LocalDate.class,new LocalDateAdapter()).create();
    }


    @DisplayName("获取用户信息")
    @Test
    public void getUserInfo() throws Exception {
        RequestBuilder requestBuilder =  MockMvcRequestBuilders.post("/user/getUserInfo")
                .header("token","eyJhbGciOiJIUzI1NiJ9.eyJwaG9uZSI6IjE4MioqKio1Njc4Iiwibmlja25hbWUiOiJqYWNrIiwiaWQiOjEsImlhdCI6MTYwNjcyMTgyNywiZXhwIjoxNjA3MzI2NjI3fQ.NHWvD4XsAEe5DRzdwmwpBmEXqw0XIb51LuUPn4FnHDI");
        MvcResult result = mockMvc.perform(requestBuilder).andReturn();
        log.info(result.getResponse().getContentAsString());
    }

    @DisplayName("发送验证码")
    @Test
    public void sendSMSCode() throws Exception {
        SendSMSCodeDTO sendSMSCodeDTO = new SendSMSCodeDTO();
        sendSMSCodeDTO.setPhone("18112345678");
	// 将数据转为 json
        String content = gson.toJson(sendSMSCodeDTO);
        RequestBuilder requestBuilder =  MockMvcRequestBuilders.post("/user/sendSMSCode")
                .contentType(MediaType.APPLICATION_JSON_VALUE)
                .content(content)
                .accept(MediaType.APPLICATION_JSON_UTF8_VALUE);
        MvcResult result = mockMvc.perform(requestBuilder).andReturn();
        log.info(result.getResponse().getContentAsString());
    }
    @DisplayName("验证验证码")
    @Test
    public void verifySMSCode() throws Exception {
        UserInfoPhoneDTO userInfoPhoneDTO = new UserInfoPhoneDTO();
        userInfoPhoneDTO.setPhone("18212345678");
        userInfoPhoneDTO.setValidateCode("156783");

        String content = gson.toJson(userInfoPhoneDTO);
        RequestBuilder requestBuilder =  MockMvcRequestBuilders.post("/user/verifySMSCode")
                .contentType(MediaType.APPLICATION_JSON_VALUE)
                .content(content)
                .accept(MediaType.APPLICATION_JSON_UTF8_VALUE);
        MvcResult result = mockMvc.perform(requestBuilder).andReturn();
        log.info(result.getResponse().getContentAsString());
    }
}

这里我们测试 Controller,也可以测试 Service

3. 测试结果

image.png

4. 常用注解简单说明

注解名称简述
@Test表示方法是一种测试方法
@DisplayName为测试类或者测试方法自定义一个名称
@BeforeEach表示方法在每个测试方法运行前都会运行
@AfterEach表示方法在每个测试方法运行之后都会运行
@BeforeAll表示方法在所有测试方法之前运行
@AfterAll表示方法在所有测试方法之后运行
@Tag用于在类或方法级别声明用于过滤测试的标记
@Disabled用于禁用测试类或测试方法