跳到主要内容

上下文管理

DeepSeek V3 中英对照 Context Management

每个 TestContext 为其负责的测试实例提供上下文管理和缓存支持。测试实例不会自动获得对已配置的 ApplicationContext 的访问权限。然而,如果测试类实现了 ApplicationContextAware 接口,ApplicationContext 的引用将被提供给测试实例。请注意,AbstractJUnit4SpringContextTestsAbstractTestNGSpringContextTests 实现了 ApplicationContextAware 接口,因此会自动提供对 ApplicationContext 的访问权限。

提示

@Autowired ApplicationContext

作为实现 ApplicationContextAware 接口的替代方案,你可以通过在字段或 setter 方法上使用 @Autowired 注解来为你的测试类注入应用上下文,如下例所示:

@SpringJUnitConfig
class MyTest {

@Autowired 1
ApplicationContext applicationContext;

// class body...
}
java
  • 注入 ApplicationContext

类似地,如果你的测试配置为加载 WebApplicationContext,你可以将 web 应用上下文注入到你的测试中,如下所示:

@SpringJUnitWebConfig 1
class MyWebAppTest {

@Autowired 2
WebApplicationContext wac;

// class body...
}
java
  • 配置 WebApplicationContext

  • 注入 WebApplicationContext

通过 @Autowired 进行的依赖注入由 DependencyInjectionTestExecutionListener 提供,该监听器默认已配置(参见 测试夹具的依赖注入)。

使用 TestContext 框架的测试类不需要扩展任何特定的类或实现特定的接口来配置其应用程序上下文。相反,配置是通过在类级别声明 @ContextConfiguration 注解来实现的。如果你的测试类没有显式声明应用程序上下文资源位置或组件类,配置的 ContextLoader 将决定如何从默认位置或默认配置类加载上下文。除了上下文资源位置和组件类外,应用程序上下文还可以通过应用程序上下文初始化器进行配置。

以下部分解释了如何使用 Spring 的 @ContextConfiguration 注解通过 XML 配置文件、Groovy 脚本、组件类(通常是 @Configuration 类)或上下文初始化器来配置测试的 ApplicationContext。或者,你也可以为实现和配置自己的自定义 SmartContextLoader 以应对高级用例。

章节摘要

📄️ 使用 XML 资源进行上下文配置

要通过使用 XML 配置文件为你的测试加载 ApplicationContext,请使用 @ContextConfiguration 注解你的测试类,并通过一个包含 XML 配置元数据资源位置的数组来配置 locations 属性。一个普通或相对路径(例如 context.xml)被视为相对于定义测试类的包路径的类路径资源。以斜杠开头的路径被视为绝对类路径位置(例如 /org/example/config.xml)。表示资源 URL 的路径(即带有 classpath:、file:、http: 等前缀的路径)将按原样使用。

📄️ 使用上下文初始化器进行上下文配置

要通过使用上下文初始化器为你的测试配置一个 ApplicationContext,请使用 @ContextConfiguration 注解你的测试类,并通过配置 initializers 属性来引用实现 ApplicationContextInitializer 的类数组。然后,声明的上下文初始化器将用于初始化为你的测试加载的 ConfigurableApplicationContext。请注意,每个声明的初始化器支持的具体 ConfigurableApplicationContext 类型必须与当前使用的 SmartContextLoader 创建的 ApplicationContext 类型兼容(通常是 GenericApplicationContext)。此外,初始化器的调用顺序取决于它们是否实现了 Spring 的 Ordered 接口,或者是否使用了 Spring 的 @Order 注解或标准的 @Priority 注解。以下示例展示了如何使用初始化器:

📄️ 上下文配置继承

@ContextConfiguration 支持布尔类型的 inheritLocations 和 inheritInitializers 属性,用于指示是否应继承由超类声明的资源位置或组件类以及上下文初始化器。这两个标志的默认值均为 true。这意味着测试类会继承由任何超类声明的资源位置或组件类以及上下文初始化器。具体来说,测试类的资源位置或组件类会被追加到由超类声明的资源位置或注解类列表中。同样,给定测试类的初始化器也会被添加到由测试超类定义的初始化器集合中。因此,子类可以选择扩展资源位置、组件类或上下文初始化器。

📄️ 使用测试属性源的上下文配置

Spring 框架对具有属性源层次结构的环境概念提供了顶级支持,并且你可以为集成测试配置特定于测试的属性源。与在 @Configuration 类上使用的 @PropertySource 注解不同,你可以在测试类上声明 @TestPropertySource 注解,以声明测试属性文件的资源位置或内联属性。这些测试属性源会被添加到为注解的集成测试加载的 ApplicationContext 的 Environment 中的 PropertySources 集合中。

📄️ 使用 Web Mocks

为了提供全面的 Web 测试支持,TestContext 框架默认启用了 ServletTestExecutionListener。当针对 WebApplicationContext 进行测试时,该 TestExecutionListener 会在每个测试方法执行之前,使用 Spring Web 的 RequestContextHolder 设置默认的线程本地状态,并根据 @WebAppConfiguration 配置的基础资源路径创建 MockHttpServletRequest、MockHttpServletResponse 和 ServletWebRequest。ServletTestExecutionListener 还确保 MockHttpServletResponse 和 ServletWebRequest 可以被注入到测试实例中,并且在测试完成后清理线程本地状态。

📄️ 上下文故障阈值

自 Spring Framework 6.1 起,引入了一种上下文失败阈值策略,该策略有助于避免重复尝试加载失败的 ApplicationContext。默认情况下,失败阈值设置为 1,这意味着对于给定的上下文缓存键(参见 \[Context Caching]\(Context Caching)),只会尝试加载一次 ApplicationContext。任何后续尝试为相同的上下文缓存键加载 ApplicationContext 的操作都会立即抛出一个 IllegalStateException,并附带一条错误信息,解释该尝试已被预先跳过。这种行为通过避免重复尝试加载永远不会成功加载的 ApplicationContext,使得单个测试类和测试套件能够更快地失败——例如,由于配置错误或缺少阻止上下文在当前环境中加载的外部资源。

📄️ 上下文层次结构

在编写依赖于已加载的 Spring ApplicationContext 的集成测试时,通常针对单个上下文进行测试就足够了。然而,有时针对 ApplicationContext 实例的层次结构进行测试是有益的,甚至是必要的。例如,如果你正在开发一个 Spring MVC Web 应用程序,通常会有一个由 Spring 的 ContextLoaderListener 加载的根 WebApplicationContext,以及一个由 Spring 的 DispatcherServlet 加载的子 WebApplicationContext。这将导致一个父子上下文层次结构,其中共享组件和基础设施配置在根上下文中声明,并由特定于 Web 的组件在子上下文中使用。另一个用例可以在 Spring Batch 应用程序中找到,其中通常会有一个父上下文为共享的批处理基础设施提供配置,而子上下文则为特定批处理作业的配置提供服务。