首页 > Java > java教程 > 开发/产品奇偶校验:Spring Boot Testcontainers

开发/产品奇偶校验:Spring Boot Testcontainers

DDD
发布: 2025-01-10 11:03:43
原创
568 人浏览过

介绍

开发/产品平价旨在缩小开发和生产环境之间的差距。本文针对工具差距,特别是在使用 Spring Testcontainers 进行集成测试方面,作为使开发和生产尽可能相似的一种方式。
在进行涉及数据库的集成测试时,我们必须仔细管理所有的CRUD操作。这在集中式数据库环境中至关重要,在这种环境中,诸如 TestDeleteUserByID_ShouldReturnOk() 之类的测试可能会“意外地”决定删除自 2015 年以来一直与我们合作的最忠实客户的帐户?‍♂️
为了减轻此类风险,我们可以考虑数据库事务等解决方案来隔离测试数据。例如,测试可以启动一个事务来修改数据,然后在最后回滚,从而使数据库保持原始状态。
但是,这引发了一个关键问题:测试的内容是什么?

Dev/prod parity : Spring Boot Testcontainers

如果隔离失败并且代码执行的更改未回滚,导致数据泄漏到生产环境怎么办?这种情况下的潜在损害是巨大的。

另外,使用 H2DB 等内存数据库进行独立测试也带来了一些挑战。即使设置很容易,H2DB 与 RDBMS 不同,因此开发环境和生产环境之间的测试很可能会产生不同的结果,因此我们不能相信这些结果。

https://stackoverflow.com/questions/62778900/syntax-error-h2-database-in-postgresql-compatibility

下一个问题较少的解决方案是克隆数据库,通过类似生产的环境提供风险较小的方法。然而,这种方法也有其局限性。鉴于 ORM 自动创建和设置生产数据库模式,我们需要考虑如何保持克隆的开发数据库同步。


测试您可以容器化的任何内容:数据库、消息代理等等

“Testcontainers 是一个支持 JUnit 测试的 Java 库,提供通用数据库、Selenium Web 浏览器或任何其他可以在 Docker 容器中运行的东西的轻量级一次性实例。”

它最初是为 Java 开发的,后来扩展到支持其他语言,如 Go、Rust 和 .NET。

Testcontainers 的主要思想是提供一个可从 IDE 运行的按需基础设施,无需模拟或使用内存服务即可进行测试,并且可以自动清理。

我们可以通过三个步骤来实现这一目标:

  • 启动所需的服务并通过设置 Docker 容器来准备基础设施,并将您的应用程序配置为使用此设置作为测试基础设施。
  • 在 Docker 化基础设施上运行测试。
  • 测试结束后自动清理docker化基础设施

Testcontainers 库文档


Spring Boot 测试容器实现

在集成测试的基类ApplicationIntegrationTests中,我们定义了一个静态的PostgreSQLContainer。此容器用于从此类派生的所有测试实例。

@Testcontainers 注解可以发现所有用 @Container 注解的字段,管理其容器生命周期方法,并启动容器。

  • 声明为静态字段的容器在测试方法之间共享。它们仅在执行任何测试方法之前启动一次,并在执行最后一个测试方法后停止。
  • 声明为实例字段的容器会针对每个测试方法启动和停止。

@DynamicPropertySource 注解允许我们动态地将属性注入到我们的测试环境中。

@Testcontainers
@ActiveProfiles("test")
public abstract class ApplicationIntegrationTests {
    @Container
    protected static PostgreSQLContainer<?> postgres=new PostgreSQLContainer<>("postgres:17.2-alpine")
            .withDatabaseName("testcontainersproject")
            .withUsername("root")
            .withPassword("root");

    @DynamicPropertySource
    static void initialize(DynamicPropertyRegistry registry)
    {
        registry.add("spring.datasource.url",postgres::getJdbcUrl);
        registry.add("spring.datasource.username",postgres::getUsername);
        registry.add("spring.datasource.password",postgres::getPassword);
    }


}
登录后复制

或者,我们可以跳过使用@Testcontainers和@Container,而是直接使用@BeforeAll和@AfterAll来管理容器生命周期。这种方法可以更好地控制容器启动和停止的时间和方式

@BeforeAll
public static void runContainer(){
        postgres.start();
}
@AfterAll
static void stopContainers() {
    postgres.stop();
}

登录后复制

在@AfterAll回调方法中,我们显式停止Postgres容器。但是,即使我们没有显式停止容器,Testcontainers 也会在测试运行结束时自动清理并关闭容器。

现在我们可以通过扩展 ApplicationIntegrationTests 来创建集成测试,如下所示。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class CategoryControllerTest extends ApplicationIntegrationTests {
    private static final String CATEGORY_ENDPOINT="/categories";
   @Autowired
    private MockMvc mockMvc;
    @Autowired
    private CategoryRepository categoryRepository;

    @Test
    void TestGetAllCategories_ShouldReturnOk() throws Exception {

        List<Category> categories = List.of(
                new Category("Electronics", "All kinds of electronic gadgets from smartphones to laptops"),
                new Category("Books", "A wide range of books from novels to educational textbooks")
        );
        categoryRepository.saveAll(categories);
        MvcResult mvcResult=mockMvc.perform(
                get(CATEGORY_ENDPOINT).
                        contentType(MediaType.APPLICATION_JSON)
        )
                .andExpect(status().isOk())
                .andReturn();
        var response=mvcResult.getResponse().getContentAsString();
        assertNotNull(response);
        assertFalse(response.isEmpty());
    }
}
登录后复制

以上是开发/产品奇偶校验:Spring Boot Testcontainers的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板