首頁 > Java > java教程 > 開發/產品奇偶校驗:Spring Boot Testcontainers

開發/產品奇偶校驗:Spring Boot Testcontainers

DDD
發布: 2025-01-10 11:03:43
原創
516 人瀏覽過

介紹

開發/產品平價旨在縮小開發和生產環境之間的差距。本文針對工具差距,特別是在使用 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
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板