TestContext 框架支持类

本节介绍支持 Spring TestContext 框架的各种类 在 JUnit 和 TestNG 中。spring-doc.cadn.net.cn

JUnit Jupiter 的 SpringExtension

Spring TestContext 框架提供了与 JUnit Jupiter 测试的完全集成 框架,在 JUnit 5 中引入。通过使用@ExtendWith(SpringExtension.class),您可以实现基于 Jupiter 的标准单元 和集成测试,同时获得 TestContext 框架的好处, 例如支持加载应用程序上下文、测试实例的依赖注入、 事务测试方法执行,依此类推。spring-doc.cadn.net.cn

此外,由于 JUnit Jupiter 中丰富的扩展 API,Spring 提供了 Spring 支持 JUnit 4 和 测试NG:spring-doc.cadn.net.cn

以下代码列表显示了如何配置测试类以使用SpringExtension结合@ContextConfiguration:spring-doc.cadn.net.cn

// 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。spring-doc.cadn.net.cn

以下示例使用@SpringJUnitConfig减少配置量 在前面的例子中使用:spring-doc.cadn.net.cn

// 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 一起使用:spring-doc.cadn.net.cn

// 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@SpringJUnitWebConfigSpring JUnit Jupiter Testing Annotations 中了解更多详细信息。spring-doc.cadn.net.cn

依赖注入与SpringExtension

SpringExtension实现ParameterResolver来自 JUnit Jupiter 的扩展 API,它允许 Spring 为测试提供依赖注入 构造函数、测试方法和测试生命周期回调方法。spring-doc.cadn.net.cn

具体来说,SpringExtension可以从测试的ApplicationContext转换为测试构造函数和方法,这些构造函数和方法用 Spring 的@BeforeTransaction@AfterTransaction或 JUnit 的@BeforeAll,@AfterAll,@BeforeEach,@AfterEach,@Test,@RepeatedTest,@ParameterizedTest,等。spring-doc.cadn.net.cn

构造函数注入

如果 JUnit Jupiter 测试类的构造函数中的特定参数类型为ApplicationContext(或其子类型)或被注释或元注释@Autowired,@Qualifier@Value,Spring 注入该特定 参数与相应的 bean 或测试的ApplicationContext.spring-doc.cadn.net.cn

如果出现以下情况,还可以将 Spring 配置为自动连接测试类构造函数的所有参数 构造函数被认为是可自动连接的。构造函数被视为 如果满足以下条件之一(按优先级排序),则可自动切换。spring-doc.cadn.net.cn

@TestConstructor有关使用的详细信息@TestConstructor以及如何更改全局测试 构造函数自动连线模式spring-doc.cadn.net.cn

如果测试类的构造函数被认为是可自动编排的,则 Spring 承担解析构造函数中所有参数的参数的责任。 因此,没有其他ParameterResolver在 JUnit 注册 Jupiter 可以解析 此类构造函数的参数。

测试类的构造函数注入不得与 JUnit 结合使用 木星的@TestInstance(PER_CLASS)支持如果@DirtiesContext用于关闭 测试的ApplicationContext测试方法之前或之后。spring-doc.cadn.net.cn

原因是@TestInstance(PER_CLASS)指示 JUnit Jupiter 缓存测试 测试方法调用之间的实例。因此,测试实例将保留 对最初从ApplicationContext那有 随后被关闭。由于测试类的构造函数只会被调用 一旦出现这种情况,依赖注入就不会再次发生,后续测试 将与来自 closed 的 bean 进行交互ApplicationContext这可能会导致错误。spring-doc.cadn.net.cn

使用@DirtiesContext在“测试方法之前”或“测试方法之后”模式下 结合@TestInstance(PER_CLASS),必须从 Spring 配置依赖项 通过现场或入场器进样供给,以便在测试之间重新进样 方法调用。spring-doc.cadn.net.cn

在下面的示例中,Spring 注入了OrderServicebean 来自ApplicationContext加载自TestConfig.class进入OrderServiceIntegrationTests构造 函数。spring-doc.cadn.net.cn

@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-doc.cadn.net.cn

如果spring.test.constructor.autowire.mode属性是all(参见@TestConstructor), 我们可以省略@Autowired在上一个示例中的构造函数上, 导致以下结果。spring-doc.cadn.net.cn

@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-doc.cadn.net.cn

在下面的示例中,Spring 注入了OrderServiceApplicationContext加载自TestConfig.class进入deleteOrder()测试方法:spring-doc.cadn.net.cn

@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-doc.cadn.net.cn

以下示例显示了如何让 Spring 和 JUnit Jupiter 注入依赖项 进入placeOrderRepeatedly()同时测试方法。spring-doc.cadn.net.cn

@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.spring-doc.cadn.net.cn

@Nested测试类配置

Spring TestContext 框架支持在@NestedJUnit Jupiter 中的测试类,包括对继承测试类的一流支持 配置,并且此类配置将由 违约。从默认值更改INHERITmode 设置为OVERRIDE模式,您可以注释 个人@Nestedtest 类与@NestedTestConfiguration(EnclosingConfiguration.OVERRIDE).显式@NestedTestConfiguration声明将应用于带注释的测试类以及 它的任何子类和嵌套类。因此,您可以注释顶级测试类 跟@NestedTestConfiguration,这将适用于其所有嵌套测试类 递 归。spring-doc.cadn.net.cn

如果您正在开发与 Spring TestContext Framework 集成的组件 并且需要在封闭的类层次结构中支持注释继承,您必须 使用TestContextAnnotationUtils为了 荣誉@NestedTestConfiguration语义学。spring-doc.cadn.net.cn

为了允许开发团队将默认值更改为OVERRIDE–例如 为了与 Spring Framework 5.0 到 5.2 兼容 – 可以更改默认模式 通过 JVM 系统属性或spring.properties文件在 类路径。有关详细信息,请参阅“更改默认封闭配置继承模式”注释。spring-doc.cadn.net.cn

虽然下面的“Hello World”示例非常简单,但它展示了如何声明 顶级类上的通用配置,该类由其继承@Nested测试 类。在此特定示例中,只有TestConfig配置类为 继承。每个嵌套测试类都提供自己的一组活动配置文件,从而产生 不同ApplicationContext对于每个嵌套测试类(有关详细信息,请参阅上下文缓存)。 查阅支持的注解列表,查看哪些注解可以在@Nested测试类。spring-doc.cadn.net.cn

@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 的Parameterizedrunner)或第三方运行器 (例如MockitoJUnitRunner),您可以选择使用 Spring 对 JUnit 规则的支持spring-doc.cadn.net.cn

以下代码列表显示了将测试类配置为 使用自定义 Spring 运行Runner:spring-doc.cadn.net.cn

@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-doc.cadn.net.cn

Spring JUnit 4 规则

org.springframework.test.context.junit4.rulespackage 提供了以下 JUnit 4 条规则(在 JUnit 4.12 或更高版本上支持):spring-doc.cadn.net.cn

SpringClassRule是 JUnitTestRule支持 Spring 的类级功能 TestContext 框架,而SpringMethodRule是 JUnitMethodRule支持 Spring TestContext 框架的实例级和方法级特性。spring-doc.cadn.net.cn

SpringRunner,Spring 基于规则的 JUnit 支持具有以下优势: 独立于任何org.junit.runner.Runner实现,因此可以是 结合现有的替代运行器(例如 JUnit 4 的Parameterized) 或 第三方运行器(例如MockitoJUnitRunner).spring-doc.cadn.net.cn

要支持 TestContext 框架的全部功能,您必须将SpringClassRule使用SpringMethodRule.以下示例显示了正确的方法 要在集成测试中声明这些规则,请执行以下作:spring-doc.cadn.net.cn

// 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.junit4package 提供以下支持 基于 JUnit 4 的测试用例的类(在 JUnit 4.12 或更高版本上受支持):spring-doc.cadn.net.cn

AbstractJUnit4SpringContextTests是一个抽象的基测试类,它集成了 Spring TestContext 框架,具有显式ApplicationContext在 JUnit 4 环境。当您扩展AbstractJUnit4SpringContextTests,您可以访问protected applicationContext实例变量,可用于执行显式 bean 查找或测试整个上下文的状态。spring-doc.cadn.net.cn

AbstractTransactionalJUnit4SpringContextTestsAbstractJUnit4SpringContextTests这为 JDBC 添加了一些便利功能 访问。此类需要javax.sql.DataSourcebean 和PlatformTransactionManagerbean 在ApplicationContext.当您 扩展AbstractTransactionalJUnit4SpringContextTests,您可以访问protected jdbcTemplate实例变量,可用于运行 SQL 语句来查询 数据库。您可以使用此类查询来确认之前和之后的数据库状态 运行与数据库相关的应用程序代码,并且 Spring 确保此类查询在 与应用程序代码相同的事务的范围。与 ORM 工具,请务必避免误报。 正如 JDBC 测试支持中提到的,AbstractTransactionalJUnit4SpringContextTests还提供了方便的方法 委托给JdbcTestUtils通过使用上述jdbcTemplate. 此外AbstractTransactionalJUnit4SpringContextTests提供executeSqlScript(..)方法,用于针对配置的DataSource.spring-doc.cadn.net.cn

这些类方便扩展。如果您不想要测试类 要绑定到特定于 Spring 的类层次结构,您可以配置自己的自定义测试 类,使用@RunWith(SpringRunner.class)Spring 的 JUnit 规则

TestNG 支持

org.springframework.test.context.testngpackage 提供以下支持 基于 TestNG 的测试用例的类:spring-doc.cadn.net.cn

AbstractTestNGSpringContextTests是一个抽象的基测试类,它集成了 Spring TestContext 框架,具有显式ApplicationContext在 TestNG 环境。当您扩展AbstractTestNGSpringContextTests,您可以访问protected applicationContext实例变量,可用于执行显式 bean 查找或测试整个上下文的状态。spring-doc.cadn.net.cn

AbstractTransactionalTestNGSpringContextTestsAbstractTestNGSpringContextTests这为 JDBC 添加了一些便利功能 访问。此类需要javax.sql.DataSourcebean 和PlatformTransactionManagerbean 在ApplicationContext.当您 扩展AbstractTransactionalTestNGSpringContextTests,您可以访问protected jdbcTemplate实例变量,可用于运行 SQL 语句来查询 数据库。您可以使用此类查询来确认之前和之后的数据库状态 运行与数据库相关的应用程序代码,并且 Spring 确保此类查询在 与应用程序代码相同的事务的范围。与 ORM 工具,请务必避免误报。 正如 JDBC 测试支持中提到的,AbstractTransactionalTestNGSpringContextTests还提供了方便的方法 委托给JdbcTestUtils通过使用上述jdbcTemplate. 此外AbstractTransactionalTestNGSpringContextTests提供executeSqlScript(..)方法,用于针对配置的DataSource.spring-doc.cadn.net.cn

这些类方便扩展。如果您不想要测试类 要绑定到特定于 Spring 的类层次结构,您可以配置自己的自定义测试 类,使用@ContextConfiguration,@TestExecutionListeners,依此类推 使用TestContextManager.查看源代码 之AbstractTestNGSpringContextTests了解如何检测测试类的示例。