領先一步
VMware 提供培訓和認證,以加速您的進展。
了解更多Spring Boot 對 Testcontainers 的支援已經有一段時間了,而 Spring Boot 3.1 進一步改進了它。但首先,讓我們來看看 Testcontainers 是什麼以及它通常是如何使用的。
Testcontainers 是一個開放原始碼框架,用於提供拋棄式的輕量級資料庫、訊息代理、Web 瀏覽器或幾乎任何可以在 Docker 容器中執行的實例。
如果您過去使用過 Testcontainers,很有可能您一直在整合測試中使用它們
@SpringBootTest
@Testcontainers
class MyIntegrationTests {
@Container
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");
@Test
void myTest() {
// ...
}
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
}
在這個整合測試中,Neo4j 資料庫在 Testcontainer 內部啟動,並放置一個 @DynamicPropertySource
以配置 Spring Boot 以使用在容器中運行的 Neo4j 資料庫。
在 Spring Boot 3.1 中,我們新增了兩個與 Testcontainers 相關的新功能。這兩個功能都是在 ConnectionDetails
抽象之上實現的,我們在另一篇部落格文章中介紹了它。如果您還沒有讀過,請現在閱讀。這篇部落格文章的其餘部分將更有意義。
第一個功能使使用 Testcontainers 進行整合測試更容易。新的 @ServiceConnection
註釋可以用於測試的容器實例欄位上
@SpringBootTest
@Testcontainers
class MyIntegrationTests {
@Container
@ServiceConnection
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");
@Test
void myTest() {
// ...
}
}
這取代了對 @DynamicPropertySource
程式碼的需求,因此您可以直接將其刪除。
在底層,@ServiceConnection
發現註釋的容器類型,並為其建立一個 ConnectionDetails
Bean。在我們的範例中,Bean 將是一個 Neo4jConnectionDetails
。Neo4j 的 Spring Boot 自動配置會使用這個 Bean 並配置驅動程式以連線到在 Testcontainer 中運行的 Neo4j 伺服器。 這適用於 Testcontainers 支援的許多不同容器類型。如果您正在使用 GenericContainer
,我們將查看映像名稱以推斷容器的類型。如果您正在使用我們無法識別名稱的自定義映像,您可以使用 @ServiceConnection
註釋的 name
屬性來引導我們到正確的方向。
使用 @ServiceConnection
註釋容器欄位有幾個優點。首先,您需要輸入的程式碼更少。其次,您的整合測試和 Spring Boot 自動配置之間不再有透過屬性的「字串式」類型耦合。第三,您不必查找(或記住)屬性名稱。
我們認為這是一個非常棒的功能,並且足以成為升級到 Spring Boot 3.1 的理由。如果您還沒有被說服,讓我們向您展示另一個很棒的功能:開發時的 Testcontainers。
大多數應用程式都需要某種類型的外部服務,例如,PostgreSQL 資料庫、Redis 伺服器或 Zipkin 後端。通常,這些服務是透過在接觸程式碼之前從 readme 執行一些 docker run
命令來提供的,或者您使用類似 Docker Compose 的東西(Spring Boot 3.1 也新增了一些很棒的新功能)。
有了開發時的 Testcontainers,您現在可以在工具箱中獲得另一個工具。為什麼您應該僅將 Testcontainers 用於整合測試?從技術上講,沒有什麼可以阻止您在生產程式碼中啟動 Testcontainers,然後放置屬性以連線到這些容器。即使在 3.1 之前的 Spring Boot 上,這也可以正常運作。
這種方法的缺點是,您現在需要在編譯類別路徑上擁有 Testcontainers 依賴項,並且很有可能這個依賴項也包含在您的 Fat JAR 中。 使用 Spring Boot 3.1,有一種更好的方法:將 Testcontainers 依賴項保留在 test
範圍內。您需要做的就是在您的 test 程式碼中建立一個新的 main
方法
public class TestMyApplication {
public static void main(String[] args) {
SpringApplication.from(MyApplication::main).run(args);
}
}
這個 test-main
方法使用新的 SpringApplication.from
方法委託給您在生產程式碼中的「真實」main 方法。
您現在可以建立一個 @TestConfiguration
,它為您在開發應用程式時需要的 Testcontainers 定義 Bean
@TestConfiguration(proxyBeanMethods = false)
class MyContainersConfiguration {
@Bean
@ServiceConnection
Neo4jContainer<?> neo4jContainer() {
return new Neo4jContainer<>("neo4j:5");
}
}
請注意,這個 Bean 方法使用 @ServiceConnection
進行註釋,以便 Spring Boot 自動建立與在容器中運行的服務的連線。這個容器的生命週期由 Spring Boot 管理。我們在應用程式啟動時啟動容器,並在應用程式停止時關閉容器。
完成後,回到您的 test-main
方法並將其指向新建立的 @TestConfiguration
public class TestMyApplication {
public static void main(String[] args) {
SpringApplication.from(MyApplication::main)
.with(MyContainersConfiguration.class)
.run(args);
}
}
現在您可以從 IDE 啟動這個 test-main
方法,容器會自動啟動,並且 Spring Boot 會建立與它們的連線。您不必設定任何配置屬性,並且 Spring Boot 會確保在應用程式停止時關閉容器。如果您喜歡從終端機運行您的應用程式,我們也為您提供了支援。用於 Gradle 和 Maven 的 Spring Boot 插件學會了運行這個 test-main
方法。使用 Gradle,它是 ./gradlew bootTestRun
,使用 Maven,它是 ./mvnw spring-boot:test-run
。
需要注意的是,每次重新啟動應用程式時,您的容器都會關閉,並且會遺失它們的資料。這可以透過兩種方式解決:第一種是使用 Spring Boot devtools,然後使用 @RestartScope
註釋容器的 Bean 方法。當 devtools 重新啟動您的應用程式時,這些容器不會重新啟動。這意味著您不必每次在應用程式中更改某些內容時都等待容器啟動,並且容器會保留它們的資料。
第二種方式是 Testcontainers 中一個名為 可重複使用的容器的功能
@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {
@Bean
@ServiceConnection
public Neo4jContainer<?> neo4jContainer() {
return new Neo4jContainer<>("neo4j:5").withReuse(true);
}
}
當應用程式關閉時,這些容器不會停止。這是一個實驗性的 Testcontainers 功能,因此使用它需要您自行承擔風險。
為了完整起見,以下是我們目前支援的容器列表
CassandraContainer
CouchbaseContainer
ElasticsearchContainer
redis
或 openzipkin/zipkin
的 GenericContainer
JdbcDatabaseContainer
KafkaContainer
MongoDBContainer
MariaDBContainer
MSSQLServerContainer
MySQLContainer
Neo4jContainer
OracleContainer
PostgreSQLContainer
RabbitMQContainer
RedpandaContainer
我們希望您喜歡這些新功能,它們將幫助您編寫更棒的應用程式。請閱讀文件以開始使用,如果您發現任何問題或有任何改進的想法,請與我們聯繫!