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

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

Spring Framework 对具有 属性源的层次结构,并且您可以使用特定于测试的集成测试来配置集成测试 属性来源。与@PropertySource用于@Configuration类,您可以声明@TestPropertySource测试上的注释 class 来声明测试属性文件或内联属性的资源位置。 这些测试属性源将添加到PropertySourcesEnvironment对于ApplicationContext加载以进行带注释的集成测试。spring-doc.cadn.net.cn

您可以使用@TestPropertySourceSmartContextLoaderSPI 的@TestPropertySource不支持旧版的实现ContextLoaderSPI.spring-doc.cadn.net.cn

实现SmartContextLoader访问合并的测试属性源值 通过getPropertySourceDescriptors()getPropertySourceProperties()方法MergedContextConfiguration.spring-doc.cadn.net.cn

声明测试属性源

您可以使用locationsvalue属性@TestPropertySource.spring-doc.cadn.net.cn

默认情况下,传统和基于 XMLjava.util.Properties文件格式是 支持——例如,"classpath:/com/example/test.properties""file:///path/to/file.xml".从 Spring Framework 6.1 开始,您可以配置自定义PropertySourceFactory通过factory属性@TestPropertySource为了 支持不同的文件格式,如JSON、YAML等。spring-doc.cadn.net.cn

每条路径都被解释为一个弹簧Resource.普通路径(例如"test.properties") 被视为相对于包的类路径资源 其中定义了测试类。以斜杠开头的路径被视为 absolute 类路径资源(例如:"/org/example/test.xml").一条路径 引用 URL(例如,以classpath:,file:http:) 是 使用指定的资源协议加载。spring-doc.cadn.net.cn

路径中的属性占位符(例如${…​}) 将针对Environment.spring-doc.cadn.net.cn

从 Spring Framework 6.1 开始,还支持资源位置模式—— 例"classpath*:/config/*.properties".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 指定具有绝对路径的属性文件。

您可以使用properties属性@TestPropertySource,如下一个示例所示。都 键值对被添加到封闭的Environment作为单次测试PropertySource具有最高优先级。spring-doc.cadn.net.cn

键值对支持的语法与为 Java 属性文件:spring-doc.cadn.net.cn

尽管可以使用上述任何语法变体和任何数字来定义属性 键和值之间的空格,建议您使用一种语法 测试套件中的变体和一致的间距 - 例如,考虑始终 用key = value而不是key= value,key=value等。同样,如果将 使用文本块的内联属性 您应该始终使用内联文本块 整个测试套件中的属性。spring-doc.cadn.net.cn

原因是您提供的确切字符串将用于确定 上下文缓存。因此,要从上下文缓存中受益,您必须确保 您可以一致地定义内联属性。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 6.1 开始,您可以使用文本块来定义多个内联 单个属性String.以下示例使用 文本块: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 通过文本块设置两个属性。

@TestPropertySource可用作可重复的注释spring-doc.cadn.net.cn

这意味着您可以有多个声明@TestPropertySource在单个 test 类,其中locationsproperties从后来开始@TestPropertySource覆盖先前注释的注释@TestPropertySource附注。spring-doc.cadn.net.cn

此外,您可以在测试类上声明多个组合注释,每个注释都是 meta-annotated@TestPropertySource,以及所有这些@TestPropertySource声明将贡献您的测试属性源。spring-doc.cadn.net.cn

直接存在@TestPropertySource注释始终优先于 元现在@TestPropertySource附注。换句话说,locationsproperties从直接存在@TestPropertySource注释将覆盖locationsproperties@TestPropertySource注释用作 元注释。spring-doc.cadn.net.cn

默认属性文件检测

如果@TestPropertySource被声明为空注解(即,没有显式 值locationsproperties属性),则尝试检测 默认属性文件。例如 如果带注释的测试类是com.example.MyTest,相应的默认属性 file 是classpath:com/example/MyTest.properties.如果无法检测到默认值,则IllegalStateException被抛出。spring-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.这意味着测试类继承位置和内联属性 由任何超类声明。具体来说,位置和内联属性 test 类附加到超类声明的位置和内联属性。 因此,子类可以选择扩展位置和内联属性。注意 稍后出现的属性 shadow (即覆盖) 同名属性 出现得更早。此外,上述优先规则适用于继承的 测试属性源。spring-doc.cadn.net.cn

如果inheritLocationsinheritProperties属性@TestPropertySource是 设置为false,分别是测试类的位置或内联属性 shadow 并有效地替换超类定义的配置。spring-doc.cadn.net.cn

测试配置也可以从封闭类继承。看@Nested测试类配置了解详情。

在下一个示例中,ApplicationContextBaseTest仅使用base.properties文件作为测试属性源。相比之下,ApplicationContextExtendedTest通过使用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() {
	// ...
}

在下一个示例中,ApplicationContextBaseTest仅使用 内联key1财产。相比之下,ApplicationContextExtendedTest是 使用内联key1key2性能。以下示例演示了如何 要使用内联属性定义子类及其超类中的属性: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() {
	// ...
}