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

上下文层级(结构)

在编写依赖于加载的Spring ApplicationContext的集成测试时,通常测试单个上下文就足够了。但是,有时测试ApplicationContext实例的层次结构是有益的,甚至是必要的。例如,如果你正在开发一个Spring MVC Web应用程序,你通常会有一个由Spring的ContextLoaderListener加载的根WebApplicationContext和一个由Spring的DispatcherServlet加载的子WebApplicationContext。这将导致父-子上下文层次结构,在该层次结构中,共享组件和基础设施配置在根上下文中声明,并由Web特定组件在子上下文中使用。另一个用例可以在Spring Batch应用程序中找到,其中你经常有一个提供共享批处理基础结构配置的父WebApplicationContext和一个由Spring的DispatcherServlet加载的子WebApplicationContext。这将导致一个父-子上下文层次结构,其中共享组件和基础设施配置在根上下文中声明,并由Web特定组件在子上下文中消费。spring-doc.cadn.net.cn

你可以编写使用上下文层次结构的集成测试,通过在单个测试类上或在测试类层次结构内声明上下文配置并使用@注解。如果在测试类层次结构内的多个类上声明了上下文层次结构,你还可以为上下文层次结构中的特定命名级别合并或覆盖上下文配置。在合并层次结构中给定级别的配置时,配置资源类型(即XML配置文件或组件类)必须保持一致。否则,在上下文层次结构的不同级别使用不同的资源类型进行配置是完全可以接受的。spring-doc.cadn.net.cn

本节中剩余的基于 JUnit Jupiter 的示例展示了需要使用上下文层次结构的集成测试的常见配置场景。spring-doc.cadn.net.cn

单个测试类与上下文层次结构spring-doc.cadn.net.cn

ControllerIntegrationTests 代表一个典型的Spring MVC Web应用程序的集成测试场景,通过声明一个包含两个级别的上下文层次结构:一个用于根 WebApplicationContext(使用 TestAppConfig @Configuration 类加载)和一个用于调度程序Servlet WebApplicationContext(使用 WebConfig @Configuration 类加载)。自动装配到测试实例中的 WebApplicationContext 是子上下文(即层次结构中最低的上下文)。以下列表显示了这种配置场景:spring-doc.cadn.net.cn

@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextHierarchy({
	@ContextConfiguration(classes = TestAppConfig.class),
	@ContextConfiguration(classes = WebConfig.class)
})
class ControllerIntegrationTests {

	@Autowired
	WebApplicationContext wac;

	// ...
}
@ExtendWith(SpringExtension::class)
@WebAppConfiguration
@ContextHierarchy(
	ContextConfiguration(classes = [TestAppConfig::class]),
	ContextConfiguration(classes = [WebConfig::class]))
class ControllerIntegrationTests {

	@Autowired
	lateinit var wac: WebApplicationContext

	// ...
}

类层次结构与隐式父级上下文spring-doc.cadn.net.cn

此示例中的测试类在测试类层次结构中定义了一个上下文层次结构。AbstractWebTests 声明了 Spring 驱动的 Web 应用程序中根 WebApplicationContext 的配置。请注意,AbstractWebTests 并未声明 @ContextHierarchy。因此,AbstractWebTests 的子类可以选择参与上下文层次结构或遵循 @ContextConfiguration 的标准语义。SoapWebServiceTestsRestWebServiceTests 都扩展了 AbstractWebTests,并通过使用 @ContextHierarchy 定义了一个上下文层次结构。结果是加载了三个应用程序上下文(每个 @ContextConfiguration 声明一个)。基于 AbstractWebTests 中的配置加载的应用程序上下文被设置为每个具体子类加载的上下文的父上下文。以下列表显示了这种配置场景:spring-doc.cadn.net.cn

@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
public abstract class AbstractWebTests {}

@ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml"))
public class SoapWebServiceTests extends AbstractWebTests {}

@ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml"))
public class RestWebServiceTests extends AbstractWebTests {}
@ExtendWith(SpringExtension::class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
abstract class AbstractWebTests

@ContextHierarchy(ContextConfiguration("/spring/soap-ws-config.xml"))
class SoapWebServiceTests : AbstractWebTests()

@ContextHierarchy(ContextConfiguration("/spring/rest-ws-config.xml"))
class RestWebServiceTests : AbstractWebTests()

类层次结构与合并的上下文层次配置spring-doc.cadn.net.cn

这个示例中的类展示了如何使用命名层次结构来合并上下文层次结构中特定级别的配置。BaseTests 定义了层次结构中的两个级别,parentchildExtendedTests 扩展了 BaseTests,并指示 Spring TestContext Framework 合并 child 层级的上下文配置,确保在 @ContextConfiguration 中声明的名称都为 child。结果是加载了三个应用程序上下文:一个用于 /app-config.xml,一个用于 /user-config.xml,以及一个用于 {"/user-config.xml", "/order-config.xml"}/app-config.xml/user-config.xml{"/user-config.xml", "/order-config.xml"} 的上下文配置。以下列表显示了这种配置场景:spring-doc.cadn.net.cn

@ExtendWith(SpringExtension.class)
@ContextHierarchy({
	@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
	@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}

@ContextHierarchy(
	@ContextConfiguration(name = "child", locations = "/order-config.xml")
)
class ExtendedTests extends BaseTests {}
@ExtendWith(SpringExtension::class)
@ContextHierarchy(
	ContextConfiguration(name = "parent", locations = ["/app-config.xml"]),
	ContextConfiguration(name = "child", locations = ["/user-config.xml"]))
open class BaseTests {}

@ContextHierarchy(
	ContextConfiguration(name = "child", locations = ["/order-config.xml"])
)
class ExtendedTests : BaseTests() {}

类层次结构与覆盖的上下文层次配置spring-doc.cadn.net.cn

与前一个示例不同,此示例演示了如何通过在上下文层次结构中为给定的命名级别设置inheritLocations标志来覆盖配置。因此,ExtendedTests的应用上下文仅从/test-user-config.xml加载,并将其父级设置为从/app-config.xml加载的上下文。以下列出了这种配置场景:spring-doc.cadn.net.cn

@ExtendWith(SpringExtension.class)
@ContextHierarchy({
	@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
	@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}

@ContextHierarchy(
	@ContextConfiguration(
		name = "child",
		locations = "/test-user-config.xml",
		inheritLocations = false
))
class ExtendedTests extends BaseTests {}
@ExtendWith(SpringExtension::class)
@ContextHierarchy(
	ContextConfiguration(name = "parent", locations = ["/app-config.xml"]),
	ContextConfiguration(name = "child", locations = ["/user-config.xml"]))
open class BaseTests {}

@ContextHierarchy(
		ContextConfiguration(
				name = "child",
				locations = ["/test-user-config.xml"],
				inheritLocations = false
		))
class ExtendedTests : BaseTests() {}
在上下文层次结构中弄脏一个上下文
如果你使用@DirtiesContext在一个测试的上下文作为上下文层次结构的一部分进行配置时,你可以使用hierarchyMode标志位用于控制如何清除上下文缓存。有关详细信息,请参阅关于的讨论。@DirtiesContext in Spring测试注解@DirtiesContext javadoc.