在這篇短文中,我們將瞭解 Testcontainers JDBC 支援,並比較在測試中啟動Docker 容器的兩種不同方式。
最初,我們將以程式設計方式管理 Testcontainer 的生命週期。之後,我們將透過單一配置屬性簡化此設定,並利用框架的 JDBC 支援。
手動管理測試容器生命週期
Testcontainers是一個提供輕量級一次性 Docker 容器用於測試的框架。我們可以使用它對真實服務(如資料庫、訊息佇列或 Web 服務)執行測試,而無需模擬或外部依賴。
假設我們想要使用 Testcontainers 來驗證與 PostgreSQL 資料庫的互動。首先,我們將testcontainers依賴項新增到我們的pom.xml中:
<dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> <version>1.19.8</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>postgresql</artifactId> <version>1.19.8</version> <scope>test</scope> </dependency>
|
之後,我們必須管理容器的生命週期,按照幾個簡單的步驟:
- 建立容器物件
- 在所有測試之前啟動容器
- 配置應用程式以連線容器
- 測試結束時停止容器
我們可以使用 JUnit5 和 Spring Boot 註釋(例如@BeforeAll、@AfterAll和@DynamicPropertyRegistry )自己實現這些步驟:@SpringBootTest class FullTestcontainersLifecycleLiveTest { static PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:16-alpine") .withDatabaseName("test-db"); @BeforeAll static void beforeAll() { postgres.start(); } @DynamicPropertySource static void setProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgres::getJdbcUrl); registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); } @AfterAll static void afterAll() { postgres.stop(); } // tests }
|
儘管此解決方案允許我們自定義特定的生命週期階段,但它需要複雜的設定。幸運的是,該框架提供了一種方便的解決方案,可以使用最少的配置啟動容器並透過 JDBC 與它們通訊。使用 Testcontainers JDBC 驅動程式
當我們使用 JDBC 驅動程式時,Testcontainers 將自動啟動託管我們資料庫的 Docker 容器。為此,我們需要更新測試執行的 JDBC URL,並使用以下模式:“jdbc:tc:<docker-image-name>:<image-tag>:///<database-name>”。
讓我們使用此語法在測試中更新spring.datasource.url :
spring.datasource.url: jdbc:tc:postgresql:16-alpine:///test-db
不用說,這個屬性可以在專用的配置檔案中定義,也可以透過@SpringBootTest註釋在測試本身中定義:
@SpringBootTest(properties = "spring.datasource.url: jdbc:tc:postgresql:16-alpine:///test-db" ) class CustomTestcontainersDriverLiveTest { @Autowired HobbitRepository theShire; @Test void whenCallingSave_thenEntityIsPersistedToDb() { theShire.save(new Hobbit("Frodo Baggins")); assertThat(theShire.findAll()) .hasSize(1).first() .extracting(Hobbit::getName) .isEqualTo("Frodo Baggins"); } }
|
我們可以注意到,我們不再需要手動處理 PostgreSQL 容器的生命週期。測試容器處理了這種複雜性,使我們能夠專注於手頭的測試。