对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
使用测试属性源的上下文配置
Spring 框架对环境的概念具有一流的支持,其中
属性源的层次结构,并且您可以使用特定于 Test 的
property 源。与@PropertySource
注释使用的@Configuration
类中,您可以声明@TestPropertySource
测试上的注释
类来声明测试属性文件或内联属性的资源位置。
这些测试属性源将添加到PropertySources
在Environment
对于ApplicationContext
loaded 进行带注释的集成测试。
您可以使用 的实现 |
声明测试属性源
您可以使用locations
或value
属性@TestPropertySource
.
默认情况下,传统和基于 XMLjava.util.Properties
文件格式为
supported — 例如,"classpath:/com/example/test.properties"
或"file:///path/to/file.xml"
.从 Spring Framework 6.1 开始,您可以配置自定义的PropertySourceFactory
通过factory
属性@TestPropertySource
为了
支持不同的文件格式,如 JSON、YAML 等。
每个路径都解释为一个 SpringResource
.普通路径(例如"test.properties"
) 被视为相对于 package 的 Classpath 资源
其中定义了测试类。以斜杠开头的路径被视为
绝对 Classpath 资源(例如:"/org/example/test.xml"
).一条
引用一个 URL(例如,前缀为classpath:
,file:
或http:
) 是
使用指定的资源协议加载。
路径中的属性占位符(如${…}
) 将针对Environment
.
从 Spring Framework 6.1 开始,还支持资源位置模式——
例"classpath*:/config/*.properties"
.
以下示例使用测试属性文件:
-
Java
-
Kotlin
@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
// class body...
}
1 | 指定具有绝对路径的属性文件。 |
@ContextConfiguration
@TestPropertySource("/test.properties") (1)
class MyIntegrationTests {
// class body...
}
1 | 指定具有绝对路径的属性文件。 |
您可以使用properties
属性@TestPropertySource
,如下例所示。都
键值对被添加到封闭的Environment
作为单个测试PropertySource
具有最高优先级。
键值对支持的语法与为 Java 属性文件:
-
key=value
-
key:value
-
key value
尽管可以使用上述任何语法变体和任意数量的
的 key 和 value 之间的空格,建议您使用一种语法
variant 和一致的间距 — 例如,考虑 Always
用 原因是您提供的确切字符串将用于确定 上下文缓存。因此,要从上下文缓存中受益,您必须确保 您可以一致地定义内联属性。 |
下面的示例设置两个内联属性:
-
Java
-
Kotlin
@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
.以下示例使用
文本块:
-
Java
-
Kotlin
@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
声明为空注解(即,没有显式
的值locations
或properties
属性),则尝试检测
default 属性文件。例如
如果带注释的测试类为com.example.MyTest
、相应的默认属性
file 为classpath:com/example/MyTest.properties
.如果无法检测到默认值,则IllegalStateException
被抛出。
优先
测试属性的优先级高于作系统的
环境、Java 系统属性或应用程序添加的属性源
通过使用@PropertySource
或以编程方式。因此,测试属性可以
用于选择性地覆盖从 System 和 Application 属性加载的属性
来源。此外,内联属性的优先级高于加载的属性
从资源位置。但是请注意,通过@DynamicPropertySource
有
比通过@TestPropertySource
.
在下一个示例中,timezone
和port
属性以及"/test.properties"
覆盖 System 中定义的任何同名属性
和应用程序属性源。此外,如果"/test.properties"
file 定义
条目的timezone
和port
属性被内联的
使用properties
属性。以下示例显示了如何作
要在 File 和 Inline 中指定属性:
-
Java
-
Kotlin
@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
支持布尔值inheritLocations
和inheritProperties
属性,这些属性表示属性文件的资源位置是否内联
超类声明的属性应该被继承。这两个标志的默认值
是true
.这意味着测试类继承 locations 和 inlined 属性
由任何超类声明。具体来说,一个
test 类附加到 superclasses 声明的 locations 和 inlined 属性中。
因此,子类可以选择扩展 locations 和 inlined 属性。注意
稍后出现的属性会隐藏(即 override)同名的属性
出现得更早。此外,上述优先规则也适用于继承的
test 属性源。
如果inheritLocations
或inheritProperties
属性@TestPropertySource
是
设置为false
、 locations 或 inlined 属性,分别为 test 类
shadow 并有效地替换 superclasses 定义的配置。
从 Spring Framework 5.3 开始,测试配置也可以从封闭中继承
类。看@Nested test 类配置了解详情。 |
在下一个示例中,ApplicationContext
为BaseTest
仅使用base.properties
file 作为测试属性源。相比之下,ApplicationContext
为ExtendedTest
使用base.properties
和extended.properties
文件作为测试属性源位置。以下示例显示了如何定义
子类及其超类中的属性properties
文件:
-
Java
-
Kotlin
@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() {
// ...
}
在下一个示例中,ApplicationContext
为BaseTest
仅使用
内联key1
财产。相比之下,ApplicationContext
为ExtendedTest
是
使用内联key1
和key2
性能。以下示例显示了如何作
要使用 inline properties 在 subclass 及其 superclass 中定义 properties:
-
Java
-
Kotlin
@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() {
// ...
}