对于最新的稳定版本,请使用 Spring Framework 7.0.6!spring-doc.cadn.net.cn

使用测试属性源的上下文配置

Spring框架对环境概念提供了一流的支持,支持属性源的层次结构,并且您可以使用特定于测试的属性源配置集成测试。与在@PropertySource类上使用的@Configuration注解不同,您可以在测试类上声明@TestPropertySource注解,以声明测试属性文件的资源位置或内联属性。这些测试属性源将被添加到为带注解的集成测试加载的ApplicationContextEnvironment中的PropertySources集合中。spring-doc.cadn.net.cn

您可以将@TestPropertySource与任何实现了SmartContextLoader SPI的版本一起使用,但在较旧的ContextLoader SPI实现中不支持@TestPropertySourcespring-doc.cadn.net.cn

Implementations of SmartContextLoader gain access to merged test property source values through the getPropertySourceLocations() and getPropertySourceProperties() methods in MergedContextConfiguration.spring-doc.cadn.net.cn

声明测试属性源

您可以通过使用locationsvalue属性来配置测试属性文件。spring-doc.cadn.net.cn

同时支持传统的和基于XML的属性文件格式——例如,"classpath:/com/example/test.properties""file:///path/to/file.xml"spring-doc.cadn.net.cn

每个路径被解释为Spring Resource。一个普通的路径(例如,"test.properties") 被视为相对于定义测试类的包的类路径资源。以斜杠开头的路径被视为绝对类路径资源(例如:"/org/example/test.xml")。引用URL的路径(例如,以classpath:file:http: 开头的路径)使用指定的资源协议进行加载。不允许使用资源位置通配符(如**/*.properties):每个位置必须解析为一个确切的.properties.xml资源。spring-doc.cadn.net.cn

以下示例使用了一个测试属性文件:spring-doc.cadn.net.cn

@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
	// class body...
}
1 指定具有绝对路径的属性文件。
@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
	// class body...
}
1 指定具有绝对路径的属性文件。

您可以通过使用@TestPropertySourceproperties属性以键值对的形式配置内联属性,如下例所示。所有键值对都将作为具有最高优先级的单个测试PropertySource添加到外围的Environment中。spring-doc.cadn.net.cn

支持的键值对语法与 Java 属性文件中定义的条目语法相同:spring-doc.cadn.net.cn

以下示例设置了两个内联属性:spring-doc.cadn.net.cn

@ContextConfiguration
@TestPropertySource(properties = {"timezone = GMT", "port: 4242"}) (1)
class MyIntegrationTests {
	// class body...
}
1 使用两种变体的关键值语法设置两个属性。
@ContextConfiguration
@TestPropertySource(properties = ["timezone = GMT", "port: 4242"]) (1)
class MyIntegrationTests {
	// class body...
}
1 使用两种变体的关键值语法设置两个属性。

从Spring Framework 5.2开始,@TestPropertySource 可以用作 可重复注解。 这意味着你可以在一个单独的测试类上声明多个 @TestPropertySource,其中来自后续 @TestPropertySource 注解的 locationsproperties 会覆盖先前 @TestPropertySource 注解中的值。spring-doc.cadn.net.cn

此外,您可以在测试类上声明多个组合注解,每个注解都使用@TestPropertySource元注解,所有这些@TestPropertySource声明都将为您的测试属性源做出贡献。spring-doc.cadn.net.cn

直接呈现的@TestPropertySource注解总是优先于元呈现的@TestPropertySource注解。换句话说,直接呈现的@TestPropertySource注解中的locationsproperties将覆盖作为元注解使用的@TestPropertySource注解中的locationspropertiesspring-doc.cadn.net.cn

默认属性文件检测

如果 @TestPropertySource 被声明为一个空注解(即,没有显式指定 locationsproperties 属性的值),将尝试检测相对于声明该注解的类的默认属性文件。例如,如果被注解的测试类是 com.example.MyTest,对应的默认属性文件是 classpath:com/example/MyTest.properties。如果无法检测到默认值,则会抛出 IllegalStateExceptionspring-doc.cadn.net.cn

优先级

测试属性的优先级高于在操作系统环境中定义的属性、Java系统属性或应用程序通过声明式使用@PropertySource或编程式添加的属性源。因此,测试属性可以用来有选择地覆盖从系统和应用程序属性源加载的属性。此外,内联属性的优先级高于从资源位置加载的属性。请注意,通过@DynamicPropertySource注册的属性比通过@TestPropertySource加载的属性具有更高的优先级。spring-doc.cadn.net.cn

在下一个示例中,timezoneport 属性以及在 "/test.properties" 中定义的任何属性将覆盖在系统和应用程序属性源中定义的同名属性。此外,如果 "/test.properties" 文件为 timezoneport 属性定义了条目,那么这些条目将被使用 properties 属性声明的内联属性覆盖。以下示例展示了如何同时在文件和内联中指定属性:spring-doc.cadn.net.cn

@ContextConfiguration
@TestPropertySource(
	locations = "/test.properties",
	properties = {"timezone = GMT", "port: 4242"}
)
class MyIntegrationTests {
	// class body...
}
@ContextConfiguration
@TestPropertySource("/test.properties",
		properties = ["timezone = GMT", "port: 4242"]
)
class MyIntegrationTests {
	// class body...
}

继承和覆盖测试属性源

@TestPropertySource 支持布尔 inheritLocationsinheritProperties 属性,这些属性表示是否应继承超类声明的属性文件的位置和内联属性。这两个标志的默认值都是 true。这意味着测试类会继承任何超类声明的位置和内联属性。具体来说,测试类的位置和内联属性将附加到超类声明的位置和内联属性中。因此,子类可以选择扩展位置和内联属性。请注意,较后出现的属性会覆盖同名的较早出现的属性。此外,上述优先级规则也适用于继承的测试属性源。spring-doc.cadn.net.cn

如果在@TestPropertySource中将inheritLocationsinheritProperties属性设置为false,测试类的locations或内联属性将覆盖并有效替换超类定义的配置。spring-doc.cadn.net.cn

从 Spring Framework 5.3 开始,测试配置也可以从外围类继承。有关详细信息,请参阅 @Nested 测试类配置

在下一个示例中,ApplicationContext 对于 BaseTest 仅使用 base.properties 文件作为测试属性源进行加载。相比之下,ApplicationContext 对于 ExtendedTest 使用 base.propertiesextended.properties 文件作为测试属性源位置进行加载。以下示例展示了如何通过使用 properties 文件在子类和超类中定义属性:spring-doc.cadn.net.cn

@TestPropertySource("base.properties")
@ContextConfiguration
class BaseTest {
	// ...
}

@TestPropertySource("extended.properties")
@ContextConfiguration
class ExtendedTest extends BaseTest {
	// ...
}
@TestPropertySource("base.properties")
@ContextConfiguration
open class BaseTest {
	// ...
}

@TestPropertySource("extended.properties")
@ContextConfiguration
class ExtendedTest : BaseTest() {
	// ...
}

在下一个示例中,使用仅内联的key1属性加载ApplicationContext对于BaseTest。相反,使用内联的key1key2属性加载ApplicationContext对于ExtendedTest。以下示例展示了如何在子类及其超类中定义属性,方法是使用内联属性:spring-doc.cadn.net.cn

@TestPropertySource(properties = "key1 = value1")
@ContextConfiguration
class BaseTest {
	// ...
}

@TestPropertySource(properties = "key2 = value2")
@ContextConfiguration
class ExtendedTest extends BaseTest {
	// ...
}
@TestPropertySource(properties = ["key1 = value1"])
@ContextConfiguration
open class BaseTest {
	// ...
}

@TestPropertySource(properties = ["key2 = value2"])
@ContextConfiguration
class ExtendedTest : BaseTest() {
	// ...
}