Spring Boot Test(测试模块)详解
Spring Boot 提供了许多公用方法与注解,可以帮助开发者测试应用程序。Spring Boot 主要包括 spring-boot-test 与 spring-boot-test-autoconfigure 核心模块。Spring Boot 提供了 spring-boot-starter-test 的 Starter,主要集成了 JUnit Jupiter、AssertJ 和Hamcrest 等常用测试框架。
使用 Spring Boot Test,需要在项目中增加 spring-boot-starter-test 的 Starter 依赖,具体如下:
如果项目中依赖 spring-boot-starter-test,则自动添加以下类库。如表 1 所示:
通常情况下,Spring Boot Test 支持的测试种类可以分为以下 3 种:
使用 @SpringBootTest 的 WebEnvironment 属性来修改测试的运行方式。
示例代码如下:
通常,@WebMvcTest 仅限于单个 Controller,并结合 @MockBean 注解提供对某个类的模拟实现。@WebMvcTest 还会自动配置MockMvc。MockMvc 提供了一个强大的方法可以快速测试 MVC 控制器,并且无须启动一个完整的 HTTP 服务器。示例代码如下:
声明:《Java系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
Spring Boot Test 简介
在 Spring Boot Test 诞生之前,常用的测试框架是 JUnit 等。Spring Boot Test 诞生后,集成了上述测试框架。Spring 框架的一个主要优势是更容易集成单元测试,可以通过 new 操作符直接生成实例,或者用 mock 对象代替真实的依赖。通常,测试不只是单元测试,还有集成测试,Spring Boot Test 可以在不部署应用程序的前提下进行集成测试。使用 Spring Boot Test,需要在项目中增加 spring-boot-starter-test 的 Starter 依赖,具体如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>使用 @SpringBootTest 注解,即可进行测试。
如果项目中依赖 spring-boot-starter-test,则自动添加以下类库。如表 1 所示:
| 库 | 说 明 |
|---|---|
| JUnit | 包括JUnit 4和JUnit 5 |
| Spring Test & Spring Boot Test | 用于Spring Boot测试 |
| AssertJ | 流式的断言库 |
| Hamcrest | 匹配库 |
| Mockito | Mock框架 |
| JSONassert | 为JSON提供断言 |
| JsonPath | 为JSON提供XPATH功能 |
通常情况下,Spring Boot Test 支持的测试种类可以分为以下 3 种:
- 单元测试:主要用于测试类功能等。
- 切片测试:介于单元测试与集成测试之间,在特定环境下才能执行。
- 集成测试:测试一个完整的功能逻辑。
核心注解
为了避免复杂的配置,Spring 引入了大量的注解方式进行测试,这样可以减轻很多工作量。让读者理解并学会使用这些注解是本文学习的主要目标,了解这些注解,可以帮助读者更加容易地掌握 Spring Boot Test 的整个框架。1. @SpringBootTest注解
Spring Boot 用 @SpringBootTest 注解替代了 spring-test 中的 @ContextConfiguration 注解,该注解可以创建 ApplicationContext,而且还添加了一些其他注解来测试特定的应用。使用 @SpringBootTest 的 WebEnvironment 属性来修改测试的运行方式。
- MOCK:加载 Web 应用程序上下文并提供模拟的 Web 环境。该注解不会启动嵌入的服务器,可以结合@AutoConfigureMockMvc 和 @AutoConfigureWebTest-Client 注解使用。
- RANDOM_PORT:加载 WebServerApplicationContext 并提供真实的 Web环境,嵌入的服务器启动后可以监听随机端口。
- DEFINED_PORT:加载 WebServerApplicationContext 并提供真实的 Web 环境,嵌入的服务器启动后可以监听特定的端口。特定的端口可以从 application.properties 获取,也可以设置为默认的 8080 端口。
- NONE:使用 SpringApplication 加载 ApplicationContext,但不提供任何 Web 环境。
示例代码如下:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.Web
Environment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
//定义测试类
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RandomPortTestRestTemplateExampleTests {
@Test
void exampleTest(@Autowired TestRestTemplate restTemplate) {
String body = restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World"); //返回结果断言
}
}
2. @RunWith注解
Spring Boot Test 默认使用 JUnit 5 框架,@RunWith(SpringRunner.class) 注解可方便开发者使用 JUnit 4 框架。使用方式如下:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DemoApplicationTests { ... }
3. @WebMvcTest注解
如果要测试 Spring MVC controllers 是否按预期那样工作,则用 @WebMvcTest 注解。@WebMvcTest 注解可自动配置 Spring MVC,并会限制扫描 @Controller 和 @ControllerAdvice 等注解的 Bean。通常,@WebMvcTest 仅限于单个 Controller,并结合 @MockBean 注解提供对某个类的模拟实现。@WebMvcTest 还会自动配置MockMvc。MockMvc 提供了一个强大的方法可以快速测试 MVC 控制器,并且无须启动一个完整的 HTTP 服务器。示例代码如下:
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvc
RequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvc
ResultMatchers.*;
@WebMvcTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private MockMvc mvc; //注入MockMvc
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic"));
this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)).andExpect(status().isOk()).andExpect(content().string("Honda Civic"));
}
}
4. @WebFluxTest注解
@DataJpaTest 注解可以测试 JPA 应用。默认情况下,该注解会扫描 @Entity 注解的类及 repositories 类。@DataJpaTest 注解不会扫描 @Component 和 @Configuration-Properties 注解的对象。示例代码如下:
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.orm.jpa.*;
import static org.assertj.core.api.Assertions.*;
//JPA测试
@DataJpaTest
class ExampleRepositoryTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository repository;
@Test
void testExample() throws Exception {
this.entityManager.persist(new User("sboot", "1234"));
User user = this.repository.findByUsername("sboot");
assertThat(user.getUsername()).isEqualTo("sboot");
//断言用户名
assertThat(user.getVin()).isEqualTo("1234");
}
}
5. @DataMongoTest注解
@DataMongoTest 注解可以用来测试 MongoDB 程序。默认会配置一个嵌入的 MongoDB 并配置一个 MongoTemplate 对象,然后扫描 @Document 注解类。示例代码如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
//Mongo测试
@DataMongoTest
class ExampleDataMongoTests {
@Autowired
private MongoTemplate mongoTemplate;
...
}
6. @DataRedisTest注解
@DataRedisTest 注解用来测试 Redis 应用程序。示例代码如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest;
//Redis测试
@DataRedisTest
class ExampleDataRedisTests {
@Autowired
private YourRepository repository;
...
}
7. @RestClientTest注解
@RestClientTest 注解用来测试 REST clients。默认情况下会自动配置 Jackson、GSON、Jsonb、RestTemplateBuilder,以及对MockRestServiceServer 的支持。示例代码如下:
@RestClientTest(RemoteVehicleDetailsService.class)
class ExampleRestClientTest {
@Autowired
private RemoteVehicleDetailsService service;
@Autowired
private MockRestServiceServer server;
@Test
void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails()
throws Exception {
this.server.expect(requestTo("/greet/details")).andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
String greeting = this.service.callRestService();
assertThat(greeting).isEqualTo("hello");
}
}
8. @AutoConfigureMockMvc注解
@SpringBootTest 注解通常不会启动服务器,如果在测试中用 Web 端点进行测试,可以添加 MockMvc 配置。示例代码如下:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MockMvcExampleTests {
@Test
void exampleTest(@Autowired MockMvc mvc) throws Exception {
mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World"));
}
}
9. @MockBean注解
测试的过程中某些场景需要模拟一些组件,这时就需要使用 @MockBean 注解。示例代码如下:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
@SpringBootTest
class MyTests {
@MockBean
private RemoteService remoteService;
@Autowired
private Reverser reverser;
@Test
void exampleTest() {
given(this.remoteService.someCall()).willReturn("mock");
String reverse = reverser.reverseSomeCall();
assertThat(reverse).isEqualTo("kcom");
}
}声明:《Java系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。