8.5.2 使用 @DataR2dbcTest 和 Testcontainers 测试数据持久化

正如你在前面章节中可能回忆的那样,Spring Boot 允许你通过仅加载特定应用程序切片使用的 Spring 组件来运行集成测试。对于 REST API,你将为 WebFlux 切片创建测试。在这里,我将向你展示如何使用 @DataR2dbcTest 注解为 R2DBC 切片编写测试。

方法与你在第 5 章中用于测试 Catalog Service 数据层的方法相同,但有两个主要区别。首先,你将使用 StepVerifier 工具来响应式测试 OrderRepository 行为。其次,你将明确定义一个 PostgreSQL 测试容器实例。

对于 Catalog Service 应用程序,我们依赖于测试容器自动配置。在这种情况下,我们将在测试类中定义一个测试容器实例并将其标记为 @Container。然后类上的 @Testcontainers 注解将激活测试容器的自动启动和清理。最后,我们将使用 Spring Boot 提供的 @DynamicProperties 注解将测试数据库的凭据和 URL 传递给应用程序。这种定义测试容器和覆盖属性的方法是通用的,可以应用于其他场景。

现在开始写代码。创建一个 OrderRepositoryR2dbcTests 类并实现自动测试来验证应用程序的数据持久化层。

代码清单 8.30 Data R2DBC 切片的集成测试

package com.polarbookshop.orderservice.order.domain;

import com.polarbookshop.orderservice.config.DataConfig;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import reactor.test.StepVerifier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;

@DataR2dbcTest // 标识专注于 R2DBC 组件的测试类
@Import(DataConfig.class)
@Testcontainers
class OrderRepositoryR2dbcTests {

 private static final String POSTGRESQL_IMAGE = "postgres:14.4";

 @Container // 标识用于测试的 PostgreSQL 容器
 static PostgreSQLContainer<?> postgresql =
 new PostgreSQLContainer<>(DockerImageName.parse(POSTGRESQL_IMAGE))
 .withDatabaseName("polardb_order")
 .withUsername("user")
 .withPassword("password");

 @DynamicPropertySource
 static void postgresqlProperties(DynamicPropertyRegistry registry) {
 registry.add("spring.r2dbc.url", () ->
 String.format("r2dbc:postgresql://%s:%d/%s",
 postgresql.getHost(),
 postgresql.getFirstMappedPort(),
 postgresql.getDatabaseName()));
 registry.add("spring.r2dbc.username", postgresql::getUsername);
 registry.add("spring.r2dbc.password", postgresql::getPassword);
 }

 @Autowired
 private OrderRepository orderRepository;

 @Test
 void whenFindAllThenReturnAllOrders() {
 StepVerifier.create(orderRepository.findAll())
 .expectNextCount(0)
 .verifyComplete();
 }

 @Test
 void whenSaveOrderThenReturnSavedOrder() {
 var order = Order.of("1234567890", "Title", "Author", 1, OrderStatus.ACCEPTED);
 StepVerifier.create(orderRepository.save(order))
 .expectNextMatches(savedOrder ->
 savedOrder.id() != null &&
 savedOrder.isbn().equals("1234567890"))
 .verifyComplete();
 }
}

这个测试类:

  1. 使用 Testcontainers 启动一个真实的 PostgreSQL 容器
  2. 配置 Spring Data R2DBC 连接到测试数据库
  3. 测试 OrderRepository 的基本操作

运行测试:

$ ./gradlew test --tests OrderRepositoryR2dbcTests

本章小结

在本章中,你学习了:

  • 响应式编程基础——事件循环模型、Reactive Streams、Project Reactor
  • Mono 和 Flux——响应式流的两种核心类型
  • Spring WebFlux——构建响应式 Web 应用程序
  • Spring Data R2DBC——响应式数据持久化
  • Spring WebClient——响应式 HTTP 客户端
  • 弹性模式——超时、重试和故障转移
  • 响应式测试——使用 StepVerifier、MockWebServer 和 Testcontainers

响应式应用程序提供了更好的可扩展性和资源利用率,但也引入了额外的复杂性。在选择是否使用响应式编程时,请权衡利弊。

在下一章中,我们将探讨 API 网关和断路器,这是构建弹性分布式系统的另一个重要方面。

results matching ""

    No results matching ""