此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

使用动态属性源的上下文配置

Spring TestContext 框架通过DynamicPropertyRegistry@DynamicPropertySource注解和DynamicPropertyRegistrar应用程序接口。spring-doc.cadn.net.cn

动态属性源基础架构最初设计为允许属性 从基于 Testcontainers 的测试中轻松暴露给 Spring 集成测试。但是,这些功能可以与任何形式的外部资源一起使用 其生命周期在测试的ApplicationContext或者 bean 生命周期由测试的ApplicationContext.spring-doc.cadn.net.cn

优先

动态属性的优先级高于从@TestPropertySource, 作系统的环境、Java 系统属性或由 应用程序使用@PropertySource或以编程方式。因此 动态属性可用于选择性地覆盖通过@TestPropertySource、系统属性源和应用程序属性源。spring-doc.cadn.net.cn

DynamicPropertyRegistry

一个DynamicPropertyRegistry用于将名称-值对添加到Environment. 值是动态的,并通过Supplier仅当属性 已解决。通常,方法引用用于提供值。以下内容 各节提供了如何使用DynamicPropertyRegistry.spring-doc.cadn.net.cn

@DynamicPropertySource

@TestPropertySource注解,以及@DynamicPropertySource可应用于static方法,以便使用 dynamic values 设置为PropertySourcesEnvironment对于ApplicationContextloaded 进行集成测试。spring-doc.cadn.net.cn

集成测试类中带有@DynamicPropertySource必须 是static并且必须接受单个DynamicPropertyRegistry论点。请参阅 的类级 javadocDynamicPropertyRegistry了解更多详情。spring-doc.cadn.net.cn

如果您使用@DynamicPropertySource在基类中,并发现子类中的测试 失败,因为 Dynamic 属性在子类之间发生了变化,你可能需要注解 你的基类替换为@DirtiesContext确保每个子类都有自己的ApplicationContext使用正确的动态 性能。spring-doc.cadn.net.cn

以下示例使用 Testcontainers 项目来管理外部的 Redis 容器 SpringApplicationContext.托管式 Redis 的 IP 地址和端口 容器可供测试的ApplicationContext通过redis.hostredis.port性能。这些属性可以通过 Spring 的Environment抽象或直接注入到 Spring 管理的组件中 —— 用于 示例,通过@Value("${redis.host}")@Value("${redis.port}")分别。spring-doc.cadn.net.cn

@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

作为实施的替代方案@DynamicPropertySourceIntegration Test 中的方法 类中,您可以注册DynamicPropertyRegistrarAPI 作为 bean 在测试的ApplicationContext.这样做可以支持其他用途 无法使用@DynamicPropertySource方法。例如,由于DynamicPropertyRegistrar本身就是ApplicationContext,它可以交互 替换为上下文中的其他 bean,并注册源自 那些豆子。spring-doc.cadn.net.cn

测试中的任何 beanApplicationContext实现DynamicPropertyRegistrar接口将在单例之前被自动检测并预先初始化 pre-instantiation 阶段和accept()此类 bean 的方法将使用DynamicPropertyRegistry执行实际的动态属性注册 代表注册商。spring-doc.cadn.net.cn

与其他 bean 的任何交互都会导致对其他 bean 的 Eager 初始化 bean 及其依赖项。

以下示例演示了如何实现DynamicPropertyRegistrar作为 Lambda 表达式,该表达式为ApiServer豆。这api.url属性可以通过 Spring 的Environmentabstraction 或 injected 直接进入其他 Spring 管理的组件 —— 例如,通过@Value("${api.url}"), 和api.url属性将从ApiServer豆。spring-doc.cadn.net.cn

@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)
	}
}