Spring-Boot-Unit-Test
Spring Boot 提供了丰富的测试功能,主要由以下两个模块组成:
- spring-boot-test:提供测试核心功能。
- spring-boot-test-autoconfigure:提供对测试的自动配置。
Spring Boot 提供了一个 spring-boot-starter-test一站式启动器,如以下依赖配置所示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
测试启动器依赖不仅包含以上两个 Spring Boot模块,还包含 Spring Test 测试模块,以及其他
第三方测试类库,如下所示。
- JUnit 5:Java 最主流的单元测试框架。
- AssertJ:一款快速断言库。
- Hamcrest:一款单元测试匹配库。
- Mockito:一款 Mock 测试框架。
- JSONassert:一款 JSON 断言库。
- JsonPath:一款 JSON XPath 库。
更多测试相关的依赖可见具体的依赖关系树
以上这些都是 Spring Boot 提供的常用的测试类库,如果上面的测试类库还不能满足你的需要,也可以任意添加以上没有的类库。
现在基本上使用的是 JUnit 5,如果应用还在使用JUnit 4 写的单元测试用例,那么也可以使用JUnit 5 的 Vintage 引擎来运行,如下面的依赖配置所示。
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
需要排除 hamcrest-core 依赖,因为该依赖已经改坐标了,并且默认内置在Spring Boot依赖管理中,如上面的依赖关系树所示,最新的 Hamcrest依赖已经是org.hamcrest:hamcrest坐标了。
Spring Boot提供了一个 @SpringBootTest 注解,用在单元测试类上以启用支持Spring Boot特性的单元测试,如果使用的是JUnit 4,那么测试类上还需要额外的@RunWith(SpringRunner. class)注解,然后在测试类方法上添加 @Test 注解即可,每一个 @Test 注解修饰的方法就是一个单元测试方法。
@SpringBootTest 注解有一个最重要的 webEnvironment 环境参数,支持以下几种环境设置:
-
MOCK(默认):加载一个
Web ApplicationContext并提供一个Mock Web Environment,但不会启动内嵌的 Web 服务器,并可以结合@AutoConfifigureMockMvcor和@AutoConfifigure-WebTestClient注解一起使用进行 Mock 测试。 -
RANDOM_PORT:加载一个
WebServerApplicationContext,以及提供一个真实的Web Environment,并以随机端口启动内嵌服务器。 -
DEFINED_PORT:和 RANDOM_PORT 一样,不同的是 DEFINED_PORT 是以应用指定的端口运行的,默认端口为 8080。
-
NONE:加载一个
ApplicationContext,但不会提供任何Web Environment。
如果使用的 @SpringBootTest 注解不带任何参数,则默认为 Mock 环境。
真实环境测试
在 @SpringBootTest 注解中指定基于随机端口的真实Web环境,然后在类成员变量或 者方法参数上注入 TestRestTemplate 实例,就可以完成对 Spring MVC接口的真实环境测试。
下面是一个基于随机端口的真实环境的测试用例:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MvcTest {
@Test
public void getUserTest(@Autowired TestRestTemplate testRestTemplate) {
Map<String, String> multiValueMap = new HashMap<>();
multiValueMap.put("username", "Java 技术栈 ");
Result result = testRestTemplate.getForObject("/user/get?username={username}",
Result.class, multiValueMap);
assertThat(result.getCode()).isEqualTo(0);
assertThat(result.getMsg()).isEqualTo("ok");
}
}
测试当前应用下的 /user/get 接口,传入对应的用户名参数,最后检查接口返回结果是否和预期一致,测试结果如下图所示。
单元测试通过,从执行日志可以看到,它启动了一个嵌入式的 Tomcat 容器来测试真实的 Web应用环境。
Mock 环境测试
通过在类上面使用 @AutoConfifigureMockMvc 注解,然后在类成员变量或者方法参数上注入MockMvc 实例,就可以完成对 Spring MVC 接口的 Mock 测试。
下面是一个基于默认 Mock 环境的测试用例:
@SpringBootTest
@AutoConfigureMockMvc
class MockMvcTests {
@Test
public void getUserTest(@Autowired MockMvc mvc) throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/user/get?username={username}", "test"))
.andExpect(status().isOk())
.andExpect(content().string("{\"code\":0,\"msg\":\"ok\",\"data\":\"test\"}"));
}
}
测试当前应用下的 /user/get 接口,传入对应的用户名参数,最后检查请求状态是否OK(200),响应的内容是否和预期一致,测试结果如下图所示。