TestContext 框架支持类
本节介绍支持 Spring TestContext 框架的各种类 在 JUnit 和 TestNG 中。
JUnit Jupiter 的 SpringExtension
Spring TestContext 框架提供了与 JUnit Jupiter 测试的完全集成
框架,在 JUnit 5 中引入。通过使用@ExtendWith(SpringExtension.class)
,您可以实现基于 Jupiter 的标准单元
和集成测试,同时获得 TestContext 框架的好处,
例如支持加载应用程序上下文、测试实例的依赖注入、
事务测试方法执行,依此类推。
此外,由于 JUnit Jupiter 中丰富的扩展 API,Spring 提供了 Spring 支持 JUnit 4 和 测试NG:
-
测试构造函数、测试方法和测试生命周期回调的依赖注入 方法。看Dependency 使用
SpringExtension
了解更多详情。 -
对条件的强大支持 基于 SpEL 表达式、环境变量、系统属性、 等等。请参阅文档
@EnabledIf
和@DisabledIf
在 Spring JUnit Jupiter Testing Annotations 中了解更多详细信息和示例。 -
自定义组合的注释,结合了来自 Spring 和 JUnit Jupiter 的注释。看 这
@TransactionalDevTestConfig
和@TransactionalIntegrationTest
元注释支持中的示例 更多细节。
以下代码列表显示了如何配置测试类以使用SpringExtension
结合@ContextConfiguration
:
-
Java
-
Kotlin
// Instructs JUnit Jupiter to extend the test with Spring support.
@ExtendWith(SpringExtension.class)
// Instructs Spring to load an ApplicationContext from TestConfig.class
@ContextConfiguration(classes = TestConfig.class)
class SimpleTests {
@Test
void testMethod() {
// test logic...
}
}
// Instructs JUnit Jupiter to extend the test with Spring support.
@ExtendWith(SpringExtension::class)
// Instructs Spring to load an ApplicationContext from TestConfig::class
@ContextConfiguration(classes = [TestConfig::class])
class SimpleTests {
@Test
fun testMethod() {
// test logic...
}
}
由于您也可以在 JUnit 5 中使用注释作为元注释,因此 Spring 提供了@SpringJUnitConfig
和@SpringJUnitWebConfig
组合注释以简化
测试的配置ApplicationContext
和 JUnit Jupiter。
以下示例使用@SpringJUnitConfig
减少配置量
在前面的例子中使用:
-
Java
-
Kotlin
// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load an ApplicationContext from TestConfig.class
@SpringJUnitConfig(TestConfig.class)
class SimpleTests {
@Test
void testMethod() {
// test logic...
}
}
// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load an ApplicationContext from TestConfig.class
@SpringJUnitConfig(TestConfig::class)
class SimpleTests {
@Test
fun testMethod() {
// test logic...
}
}
同样,以下示例使用@SpringJUnitWebConfig
创建WebApplicationContext
与 JUnit Jupiter 一起使用:
-
Java
-
Kotlin
// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load a WebApplicationContext from TestWebConfig.class
@SpringJUnitWebConfig(TestWebConfig.class)
class SimpleWebTests {
@Test
void testMethod() {
// test logic...
}
}
// Instructs Spring to register the SpringExtension with JUnit
// Jupiter and load a WebApplicationContext from TestWebConfig::class
@SpringJUnitWebConfig(TestWebConfig::class)
class SimpleWebTests {
@Test
fun testMethod() {
// test logic...
}
}
请参阅文档@SpringJUnitConfig
和@SpringJUnitWebConfig
在 Spring JUnit Jupiter Testing Annotations 中了解更多详细信息。
依赖注入与SpringExtension
这SpringExtension
实现ParameterResolver
来自 JUnit Jupiter 的扩展 API,它允许 Spring 为测试提供依赖注入
构造函数、测试方法和测试生命周期回调方法。
具体来说,SpringExtension
可以从测试的ApplicationContext
转换为测试构造函数和方法,这些构造函数和方法用 Spring 的@BeforeTransaction
和@AfterTransaction
或 JUnit 的@BeforeAll
,@AfterAll
,@BeforeEach
,@AfterEach
,@Test
,@RepeatedTest
,@ParameterizedTest
,等。
构造函数注入
如果 JUnit Jupiter 测试类的构造函数中的特定参数类型为ApplicationContext
(或其子类型)或被注释或元注释@Autowired
,@Qualifier
或@Value
,Spring 注入该特定
参数与相应的 bean 或测试的ApplicationContext
.
如果出现以下情况,还可以将 Spring 配置为自动连接测试类构造函数的所有参数 构造函数被认为是可自动连接的。构造函数被视为 如果满足以下条件之一(按优先级排序),则可自动切换。
-
构造函数的注释为
@Autowired
. -
@TestConstructor
在测试类上存在或元存在,具有autowireMode
属性设置为ALL
. -
默认的测试构造函数自动连线模式已更改为
ALL
.
看@TestConstructor
有关使用的详细信息@TestConstructor
以及如何更改全局测试
构造函数自动连线模式。
如果测试类的构造函数被认为是可自动编排的,则 Spring
承担解析构造函数中所有参数的参数的责任。
因此,没有其他ParameterResolver 在 JUnit 注册 Jupiter 可以解析
此类构造函数的参数。 |
测试类的构造函数注入不得与 JUnit 结合使用
木星的 原因是 使用 |
在下面的示例中,Spring 注入了OrderService
bean 来自ApplicationContext
加载自TestConfig.class
进入OrderServiceIntegrationTests
构造 函数。
-
Java
-
Kotlin
@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {
private final OrderService orderService;
@Autowired
OrderServiceIntegrationTests(OrderService orderService) {
this.orderService = orderService;
}
// tests that use the injected OrderService
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests @Autowired constructor(private val orderService: OrderService){
// tests that use the injected OrderService
}
请注意,此功能允许测试依赖项final
因此是不可变的。
如果spring.test.constructor.autowire.mode
属性是all
(参见@TestConstructor
),
我们可以省略@Autowired
在上一个示例中的构造函数上,
导致以下结果。
-
Java
-
Kotlin
@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {
private final OrderService orderService;
OrderServiceIntegrationTests(OrderService orderService) {
this.orderService = orderService;
}
// tests that use the injected OrderService
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests(val orderService:OrderService) {
// tests that use the injected OrderService
}
方法注入
如果 JUnit Jupiter 测试方法或测试生命周期回调方法中的参数为
类型ApplicationContext
(或其子类型)或被注释或元注释@Autowired
,@Qualifier
或@Value
,Spring 注入该特定
参数替换为测试的ApplicationContext
.
在下面的示例中,Spring 注入了OrderService
从ApplicationContext
加载自TestConfig.class
进入deleteOrder()
测试方法:
-
Java
-
Kotlin
@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {
@Test
void deleteOrder(@Autowired OrderService orderService) {
// use orderService from the test's ApplicationContext
}
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests {
@Test
fun deleteOrder(@Autowired orderService: OrderService) {
// use orderService from the test's ApplicationContext
}
}
由于ParameterResolver
在 JUnit Jupiter 中支持,您还可以
将多个依赖项注入到单个方法中,不仅来自 Spring,而且
来自 JUnit Jupiter 本身或其他第三方扩展。
以下示例显示了如何让 Spring 和 JUnit Jupiter 注入依赖项
进入placeOrderRepeatedly()
同时测试方法。
-
Java
-
Kotlin
@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {
@RepeatedTest(10)
void placeOrderRepeatedly(RepetitionInfo repetitionInfo,
@Autowired OrderService orderService) {
// use orderService from the test's ApplicationContext
// and repetitionInfo from JUnit Jupiter
}
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests {
@RepeatedTest(10)
fun placeOrderRepeatedly(repetitionInfo:RepetitionInfo, @Autowired orderService:OrderService) {
// use orderService from the test's ApplicationContext
// and repetitionInfo from JUnit Jupiter
}
}
请注意,使用@RepeatedTest
从 JUnit Jupiter 让测试方法获得访问权限
到RepetitionInfo
.
@Nested
测试类配置
Spring TestContext 框架支持在@Nested
JUnit Jupiter 中的测试类,包括对继承测试类的一流支持
配置,并且此类配置将由
违约。从默认值更改INHERIT
mode 设置为OVERRIDE
模式,您可以注释
个人@Nested
test 类与@NestedTestConfiguration(EnclosingConfiguration.OVERRIDE)
.显式@NestedTestConfiguration
声明将应用于带注释的测试类以及
它的任何子类和嵌套类。因此,您可以注释顶级测试类
跟@NestedTestConfiguration
,这将适用于其所有嵌套测试类
递 归。
如果您正在开发与 Spring TestContext Framework 集成的组件
并且需要在封闭的类层次结构中支持注释继承,您必须
使用 |
为了允许开发团队将默认值更改为OVERRIDE
–例如
为了与 Spring Framework 5.0 到 5.2 兼容 – 可以更改默认模式
通过 JVM 系统属性或spring.properties
文件在
类路径。有关详细信息,请参阅“更改默认封闭配置继承模式”注释。
虽然下面的“Hello World”示例非常简单,但它展示了如何声明
顶级类上的通用配置,该类由其继承@Nested
测试
类。在此特定示例中,只有TestConfig
配置类为
继承。每个嵌套测试类都提供自己的一组活动配置文件,从而产生
不同ApplicationContext
对于每个嵌套测试类(有关详细信息,请参阅上下文缓存)。
查阅支持的注解列表,查看哪些注解可以在@Nested
测试类。
-
Java
-
Kotlin
@SpringJUnitConfig(TestConfig.class)
class GreetingServiceTests {
@Nested
@ActiveProfiles("lang_en")
class EnglishGreetings {
@Test
void hello(@Autowired GreetingService service) {
assertThat(service.greetWorld()).isEqualTo("Hello World");
}
}
@Nested
@ActiveProfiles("lang_de")
class GermanGreetings {
@Test
void hello(@Autowired GreetingService service) {
assertThat(service.greetWorld()).isEqualTo("Hallo Welt");
}
}
}
@SpringJUnitConfig(TestConfig::class)
class GreetingServiceTests {
@Nested
@ActiveProfiles("lang_en")
inner class EnglishGreetings {
@Test
fun hello(@Autowired service:GreetingService) {
assertThat(service.greetWorld()).isEqualTo("Hello World")
}
}
@Nested
@ActiveProfiles("lang_de")
inner class GermanGreetings {
@Test
fun hello(@Autowired service:GreetingService) {
assertThat(service.greetWorld()).isEqualTo("Hallo Welt")
}
}
}
JUnit 4 支持
弹簧 JUnit 4 流轮
Spring TestContext 框架通过自定义
runner(在 JUnit 4.12 或更高版本上受支持)。通过使用@RunWith(SpringJUnit4ClassRunner.class)
或较短的@RunWith(SpringRunner.class)
变体,开发人员可以实现基于 JUnit 4 的标准单元和集成测试,以及
同时获得 TestContext 框架的好处,例如
加载应用程序上下文、测试实例的依赖注入、事务测试
方法执行,依此类推。如果要将 Spring TestContext 框架与
替代运行器(例如 JUnit 4 的Parameterized
runner)或第三方运行器
(例如MockitoJUnitRunner
),您可以选择使用 Spring 对 JUnit 规则的支持。
以下代码列表显示了将测试类配置为
使用自定义 Spring 运行Runner
:
-
Java
-
Kotlin
@RunWith(SpringRunner.class)
@TestExecutionListeners({})
public class SimpleTest {
@Test
public void testMethod() {
// test logic...
}
}
@RunWith(SpringRunner::class)
@TestExecutionListeners
class SimpleTest {
@Test
fun testMethod() {
// test logic...
}
}
在前面的示例中,@TestExecutionListeners
配置为空列表,以
禁用默认监听器,否则这将需要ApplicationContext
自
通过@ContextConfiguration
.
Spring JUnit 4 规则
这org.springframework.test.context.junit4.rules
package 提供了以下 JUnit
4 条规则(在 JUnit 4.12 或更高版本上支持):
-
SpringClassRule
-
SpringMethodRule
SpringClassRule
是 JUnitTestRule
支持 Spring 的类级功能
TestContext 框架,而SpringMethodRule
是 JUnitMethodRule
支持
Spring TestContext 框架的实例级和方法级特性。
与SpringRunner
,Spring 基于规则的 JUnit 支持具有以下优势:
独立于任何org.junit.runner.Runner
实现,因此可以是
结合现有的替代运行器(例如 JUnit 4 的Parameterized
) 或
第三方运行器(例如MockitoJUnitRunner
).
要支持 TestContext 框架的全部功能,您必须将SpringClassRule
使用SpringMethodRule
.以下示例显示了正确的方法
要在集成测试中声明这些规则,请执行以下作:
-
Java
-
Kotlin
// Optionally specify a non-Spring Runner via @RunWith(...)
@ContextConfiguration
public class IntegrationTest {
@ClassRule
public static final SpringClassRule springClassRule = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Test
public void testMethod() {
// test logic...
}
}
// Optionally specify a non-Spring Runner via @RunWith(...)
@ContextConfiguration
class IntegrationTest {
@Rule
val springMethodRule = SpringMethodRule()
@Test
fun testMethod() {
// test logic...
}
companion object {
@ClassRule
val springClassRule = SpringClassRule()
}
}
JUnit 4 基类
这org.springframework.test.context.junit4
package 提供以下支持
基于 JUnit 4 的测试用例的类(在 JUnit 4.12 或更高版本上受支持):
-
AbstractJUnit4SpringContextTests
-
AbstractTransactionalJUnit4SpringContextTests
AbstractJUnit4SpringContextTests
是一个抽象的基测试类,它集成了
Spring TestContext 框架,具有显式ApplicationContext
在
JUnit 4 环境。当您扩展AbstractJUnit4SpringContextTests
,您可以访问protected
applicationContext
实例变量,可用于执行显式
bean 查找或测试整个上下文的状态。
AbstractTransactionalJUnit4SpringContextTests
是AbstractJUnit4SpringContextTests
这为 JDBC 添加了一些便利功能
访问。此类需要javax.sql.DataSource
bean 和PlatformTransactionManager
bean 在ApplicationContext
.当您
扩展AbstractTransactionalJUnit4SpringContextTests
,您可以访问protected
jdbcTemplate
实例变量,可用于运行 SQL 语句来查询
数据库。您可以使用此类查询来确认之前和之后的数据库状态
运行与数据库相关的应用程序代码,并且 Spring 确保此类查询在
与应用程序代码相同的事务的范围。与
ORM 工具,请务必避免误报。
正如 JDBC 测试支持中提到的,AbstractTransactionalJUnit4SpringContextTests
还提供了方便的方法
委托给JdbcTestUtils
通过使用上述jdbcTemplate
.
此外AbstractTransactionalJUnit4SpringContextTests
提供executeSqlScript(..)
方法,用于针对配置的DataSource
.
这些类方便扩展。如果您不想要测试类
要绑定到特定于 Spring 的类层次结构,您可以配置自己的自定义测试
类,使用@RunWith(SpringRunner.class) 或 Spring 的 JUnit 规则。 |
TestNG 支持
这org.springframework.test.context.testng
package 提供以下支持
基于 TestNG 的测试用例的类:
-
AbstractTestNGSpringContextTests
-
AbstractTransactionalTestNGSpringContextTests
AbstractTestNGSpringContextTests
是一个抽象的基测试类,它集成了
Spring TestContext 框架,具有显式ApplicationContext
在
TestNG 环境。当您扩展AbstractTestNGSpringContextTests
,您可以访问protected
applicationContext
实例变量,可用于执行显式
bean 查找或测试整个上下文的状态。
AbstractTransactionalTestNGSpringContextTests
是AbstractTestNGSpringContextTests
这为 JDBC 添加了一些便利功能
访问。此类需要javax.sql.DataSource
bean 和PlatformTransactionManager
bean 在ApplicationContext
.当您
扩展AbstractTransactionalTestNGSpringContextTests
,您可以访问protected
jdbcTemplate
实例变量,可用于运行 SQL 语句来查询
数据库。您可以使用此类查询来确认之前和之后的数据库状态
运行与数据库相关的应用程序代码,并且 Spring 确保此类查询在
与应用程序代码相同的事务的范围。与
ORM 工具,请务必避免误报。
正如 JDBC 测试支持中提到的,AbstractTransactionalTestNGSpringContextTests
还提供了方便的方法
委托给JdbcTestUtils
通过使用上述jdbcTemplate
.
此外AbstractTransactionalTestNGSpringContextTests
提供executeSqlScript(..)
方法,用于针对配置的DataSource
.
这些类方便扩展。如果您不想要测试类
要绑定到特定于 Spring 的类层次结构,您可以配置自己的自定义测试
类,使用@ContextConfiguration ,@TestExecutionListeners ,依此类推
使用TestContextManager .查看源代码
之AbstractTestNGSpringContextTests 了解如何检测测试类的示例。 |