具有動態屬性來源的內容組態
Spring TestContext 框架透過 DynamicPropertyRegistry
、@DynamicPropertySource
註解和 DynamicPropertyRegistrar
API 提供對動態屬性的支援。
動態屬性來源基礎架構最初旨在讓基於 Testcontainers 的測試屬性能夠輕鬆地暴露給 Spring 整合測試。但是,這些功能可以與任何形式的外部資源一起使用,這些外部資源的生命週期在測試的 |
優先順序
動態屬性的優先順序高於從 @TestPropertySource
、作業系統環境、Java 系統屬性或應用程式使用 @PropertySource
以宣告方式或以程式設計方式新增的屬性來源載入的屬性。因此,動態屬性可用於選擇性地覆寫透過 @TestPropertySource
、系統屬性來源和應用程式屬性來源載入的屬性。
DynamicPropertyRegistry
DynamicPropertyRegistry
用於將名稱-值對新增至 Environment
。值是動態的,並透過僅在解析屬性時才調用的 Supplier
提供。通常,方法參考用於提供值。以下章節提供如何使用 DynamicPropertyRegistry
的範例。
@DynamicPropertySource
與在類別層級應用的 @TestPropertySource
註解相反,@DynamicPropertySource
可以應用於整合測試類別中的 static
方法,以便將具有動態值的屬性新增至 Environment
中 PropertySources
的集合,用於為整合測試載入的 ApplicationContext
。
使用 @DynamicPropertySource
註解的整合測試類別中的方法必須是 static
,並且必須接受單個 DynamicPropertyRegistry
引數。有關更多詳細資訊,請參閱 DynamicPropertyRegistry
的類別層級 javadoc。
如果您在基底類別中使用 |
以下範例使用 Testcontainers 專案在 Spring ApplicationContext
之外管理 Redis 容器。受管 Redis 容器的 IP 位址和連接埠透過 redis.host
和 redis.port
屬性提供給測試 ApplicationContext
內的組件。這些屬性可以透過 Spring 的 Environment
抽象存取,或直接注入到 Spring 管理的組件中 – 例如,分別透過 @Value("${redis.host}")
和 @Value("${redis.port}")
。
-
Java
-
Kotlin
@SpringJUnitConfig(/* ... */)
@Testcontainers
class ExampleIntegrationTests {
@Container
static GenericContainer redis =
new GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379);
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
registry.add("redis.host", redis::getHost);
registry.add("redis.port", redis::getFirstMappedPort);
}
// tests ...
}
@SpringJUnitConfig(/* ... */)
@Testcontainers
class ExampleIntegrationTests {
companion object {
@Container
@JvmStatic
val redis: GenericContainer =
GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379)
@DynamicPropertySource
@JvmStatic
fun redisProperties(registry: DynamicPropertyRegistry) {
registry.add("redis.host", redis::getHost)
registry.add("redis.port", redis::getFirstMappedPort)
}
}
// tests ...
}
DynamicPropertyRegistrar
作為在整合測試類別中實作 @DynamicPropertySource
方法的替代方案,您可以將 DynamicPropertyRegistrar
API 的實作註冊為測試 ApplicationContext
中的 Bean。這樣做可讓您支援 @DynamicPropertySource
方法無法實現的其他使用案例。例如,由於 DynamicPropertyRegistrar
本身是 ApplicationContext
中的 Bean,因此它可以與內容中的其他 Bean 互動,並註冊從這些 Bean 來源的動態屬性。
測試 ApplicationContext
中實作 DynamicPropertyRegistrar
介面的任何 Bean 都將在單例預先實例化階段之前自動偵測並主動初始化,並且此類 Bean 的 accept()
方法將使用 DynamicPropertyRegistry
調用,後者代表註冊器執行實際的動態屬性註冊。
與其他 Bean 的任何互動都會導致主動初始化這些其他 Bean 及其依賴項。 |
以下範例示範如何將 DynamicPropertyRegistrar
實作為 Lambda 運算式,該運算式為 ApiServer
Bean 註冊動態屬性。api.url
屬性可以透過 Spring 的 Environment
抽象存取,或直接注入到其他 Spring 管理的組件中 – 例如,透過 @Value("${api.url}")
,並且 api.url
屬性的值將從 ApiServer
Bean 動態擷取。
-
Java
-
Kotlin
@Configuration
class TestConfig {
@Bean
ApiServer apiServer() {
return new ApiServer();
}
@Bean
DynamicPropertyRegistrar apiPropertiesRegistrar(ApiServer apiServer) {
return registry -> registry.add("api.url", apiServer::getUrl);
}
}
@Configuration
class TestConfig {
@Bean
fun apiServer(): ApiServer {
return ApiServer()
}
@Bean
fun apiPropertiesRegistrar(apiServer: ApiServer): DynamicPropertyRegistrar {
return registry -> registry.add("api.url", apiServer::getUrl)
}
}