Context Hierarchies
在编写依赖于已加载 Spring ApplicationContext
的集成测试时,通常针对单个上下文进行测试就足够了。但是,有时针对 ApplicationContext
实例的层次结构进行测试是有益的甚至是必要的。例如,如果正在开发一个 Spring MVC Web 应用程序,则通常会加载由 Spring 的 ContextLoaderListener
加载的根 WebApplicationContext
和由 Spring 的 DispatcherServlet
加载的子 WebApplicationContext
。这将导致一个父级-子级上下文层次结构,在该层次结构中,共享组件和基础设施配置在根上下文中声明,并在子上下文中由特定于 Web 的组件使用。Spring Batch 应用程序也可以找到另一个用例,在该应用程序中,通常有一个提供共享批处理基础设施配置的父上下文以及用于特定批处理作业的配置的子上下文。
可以通过使用 @ContextHierarchy
注解在单个测试类或测试类层次结构中声明上下文配置来编写使用上下文层次结构的集成测试。如果在测试类层次结构中的多个类上声明上下文层次结构,则还可以合并或覆盖上下文层次结构中特定命名级别的上下文配置。在合并层次结构中给定级别的配置时,配置资源类型(即 XML 配置文件或组件类)必须一致。否则,完全可以接受使用不同的资源类型配置上下文层次结构中的不同级别。
本节中其余基于 JUnit Jupiter 的示例展示了需要使用上下文层次结构的集成测试的常见配置场景。
带有上下文层次结构的单个测试类
ControllerIntegrationTests
表示 Spring MVC Web 应用程序的典型集成测试场景,它声明一个由两个级别组成的上下文层次结构,它一个用于根 WebApplicationContext
(通过使用 TestAppConfig
@Configuration
类加载),另一个用于分发器 servlet WebApplicationContext
(通过使用 WebConfig
@Configuration
类加载)。自动注入测试实例的 WebApplicationContext
是子上下文的一个(即层次结构中最低的上下文)。以下清单显示了此配置场景:
-
Java
-
Kotlin
@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
// ...
}
带有隐式父上下文的类层次结构
此示例中的测试类在测试类层次结构中定义了上下文层次结构。AbstractWebTests
声明 Spring 支持的 Web 应用程序中根 WebApplicationContext
的配置。不过,请注意,AbstractWebTests
不声明 @ContextHierarchy
。因此,AbstractWebTests
的子类可以选择参与上下文层次结构或遵循 @ContextConfiguration
的标准语义。SoapWebServiceTests
和 RestWebServiceTests
都通过使用 @ContextHierarchy
扩展 AbstractWebTests
并定义上下文层次结构。结果是加载了三个应用程序上下文(一个用于每个 @ContextConfiguration
声明),并且基于 AbstractWebTests
中的配置加载的应用程序上下文被设置为为具体子类加载的每个上下文的父上下文。以下清单显示了此配置场景:
-
Java
-
Kotlin
@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()
带有合并上下文层次结构配置的类层次结构
此示例中的类展示了如何使用命名的层次结构级别来合并上下文层次结构中特定级别的配置。BaseTests
在层次结构中定义两个级别,即 parent
和 child
。ExtendedTests
扩展了 BaseTests
并指示 Spring TestContext 框架合并 child
层次结构级别的上下文配置,方法是确保 @ContextConfiguration
中 name
属性中声明的名称都是 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"}
加载的上下文的父上下文。以下清单显示了此配置场景:
-
Java
-
Kotlin
@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() {}
带有覆盖上下文层次结构配置的类层次结构
与前一个示例相反,此示例演示了如何通过将 @ContextConfiguration
中的 inheritLocations
标志设置为 false
来覆盖上下文层次结构中给定命名级别的配置。因此,ExtendedTests
的应用程序上下文仅从 /test-user-config.xml
加载,并将其父级设置为从 /app-config.xml
加载的上下文。以下清单显示了此配置场景:
-
Java
-
Kotlin
@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() {}
Dirtying a context within a context hierarchy
如果您在上下文中配置为上下级关系的一部分的测试中使用 |