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笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。