使用動態屬性源進行上下文配置
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 容器的 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)
}
}