集成测试:内存库/事务回滚/Testcontainers 简介

上一章的切片测试只验证单层,而 Repository 与数据库、Service 与事务的真实配合要靠集成测试。Spring Boot 集成测试常见三件套:内存库(快但方言有差异)、事务回滚(测试互不污染)、Testcontainers(用 Docker 拉起与生产一致的真实中间件)。

内存库:H2 + @AutoConfigureTestDatabase

测试作用域引入 H2,切片注解会自动用内置库替换真实数据源:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
</dependency>
@DataJpaTest            // 切片:JPA Repository + H2 + 自带 @Transactional
class UserRepositoryTest {
    @Autowired
    UserRepository userRepository;

    @Test
    void saveAndFind_shouldWork() {
        User u = userRepository.save(new User("张三"));
        // 输出:保存成功,主键由数据库生成
        Assertions.assertThat(u.getId()).isNotNull();

        Assertions.assertThat(userRepository.findByUsername("张三")).isPresent();
    }
}

@DataJpaTest 自带事务:每个测试方法结束后整体回滚,所以上一个用例写入的数据不会泄漏给下一个用例。

@SpringBootTest 全量集成与回滚

需要跨层验证时用全量上下文,同样可以"内存库 + 事务回滚":

@SpringBootTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY) // 用 H2 顶替配置里的数据源
@Transactional                 // 每个测试方法结束时回滚
class OrderServiceIT {
    @Autowired
    OrderService orderService;

    @Test
    void createOrder_shouldPersist() {
        orderService.create(new OrderCreateRequest(1L, 2));
        // 输出:方法内能查到刚创建的订单(同事务),测试结束后数据回滚
    }
}

注意两个失效场景:被测代码内部开了 REQUIRES_NEW 传播级别、或把操作丢进新线程/异步执行,都会脱离测试事务,回滚随之失效。

Testcontainers 简介

H2 与真实 MySQL/PG 在锁、函数、方言上总有差异,"像生产一样测"用 Testcontainers:测试前用 Docker 启动一次性容器,用完即销毁。

@Testcontainers
class UserRepositoryTC {
    @Container
    @ServiceConnection        // Spring Boot 3.1+:把容器连接信息自动注入 DataSource
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");

    @Autowired
    UserRepository userRepository;

    @Test
    void crud_againstRealPg() {
        userRepository.save(new User("张三"));
        // 输出:真实 PostgreSQL 上执行,断言不再受 H2 方言限制
    }
}

配套依赖 org.testcontainers:junit-jupiterorg.testcontainers:postgresqlspring-boot-testcontainers,版本由 Boot BOM 管理。实战要点:CI 必须能跑 Docker;容器声明为 static 单例并在多测试类间复用可显著提速;镜像版本尽量与生产一致。

小结:优先"切片 + H2"跑快反馈,核心链路用 @SpringBootTest 事务回滚隔离,需要真实中间件行为时上 Testcontainers + @ServiceConnection。

笔记加载中…