使用動態屬性源進行上下文配置
Spring TestContext Framework 透過 DynamicPropertyRegistry
、@DynamicPropertySource
註解和 DynamicPropertyRegistrar
API 支援動態屬性。
動態屬性源基礎設施最初設計用於將基於 Testcontainers 的測試中的屬性輕鬆暴露給 Spring 整合測試。然而,這些功能也可用於任何生命週期在測試的 |
優先順序
動態屬性的優先順序高於從 @TestPropertySource
、作業系統環境變數、Java 系統屬性,或應用透過宣告式(使用 @PropertySource
)或程式化方式新增的屬性源載入的屬性。因此,動態屬性可用於選擇性地覆蓋透過 @TestPropertySource
、系統屬性源和應用屬性源載入的屬性。
DynamicPropertyRegistry
DynamicPropertyRegistry
用於向 Environment
新增鍵值對。這些值是動態的,透過一個 Supplier
提供,該 Supplier
僅在屬性被解析時呼叫。通常使用方法引用來提供值。以下各節提供瞭如何使用 DynamicPropertyRegistry
的示例。
@DynamicPropertySource
與應用於類級別的 @TestPropertySource
註解不同,@DynamicPropertySource
可以應用於整合測試類中的 static
方法,以便將具有動態值的屬性新增到為該整合測試載入的 ApplicationContext
的 Environment
中的 PropertySources
集合中。
整合測試類中用 @DynamicPropertySource
註解的方法必須是 static
的,並且必須接受一個 DynamicPropertyRegistry
引數。有關更多詳細資訊,請參閱 DynamicPropertyRegistry
的類級別 javadoc。
如果在基類中使用 |
以下示例使用 Testcontainers 專案來管理 Spring ApplicationContext
外部的 Redis 容器。透過 redis.host
和 redis.port
屬性,託管 Redis 容器的 IP 地址和埠可供測試的 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 都將在單例預例項化階段之前自動檢測並急切初始化,並且將使用代表註冊器執行實際動態屬性註冊的 DynamicPropertyRegistry
呼叫這些 bean 的 accept()
方法。
與任何其他 bean 的互動都會導致這些其他 bean 及其依賴項的急切初始化。 |
以下示例演示瞭如何將 DynamicPropertyRegistrar
實現為一個 lambda 表示式,該表示式為 ApiServer
bean 註冊一個動態屬性。可以透過 Spring 的 Environment
抽象訪問 api.url
屬性,或直接注入到其他 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)
}
}