上下文缓存
一旦 TestContext 框架为某个测试加载了一个 ApplicationContext(或 WebApplicationContext),该上下文就会被缓存,并在同一测试套件中所有声明了相同唯一上下文配置的后续测试中重复使用。要理解缓存的工作原理,关键在于弄清楚“唯一”和“测试套件”的含义。
ApplicationContext 可以通过用于加载它的配置参数组合进行唯一标识。因此,该唯一的配置参数组合被用来生成一个键(key),在此键下缓存该上下文。TestContext 框架使用以下配置参数来构建上下文缓存键:
-
locations(来自@ContextConfiguration) -
classes(来自@ContextConfiguration) -
contextInitializerClasses(来自@ContextConfiguration) -
contextCustomizers(来自ContextCustomizerFactory)——包括@DynamicPropertySource方法、Bean 覆盖(例如@TestBean、@MockitoBean、@MockitoSpyBean等),以及 Spring Boot 测试支持中的各种功能。 -
contextLoader(来自@ContextConfiguration) -
parent(来自@ContextHierarchy) -
activeProfiles(来自@ActiveProfiles) -
propertySourceDescriptors(来自@TestPropertySource) -
propertySourceProperties(来自@TestPropertySource) -
resourceBasePath(来自@WebAppConfiguration)
例如,如果 TestClassA 为 @ContextConfiguration 的 locations(或 value)属性指定了 {"app-config.xml", "test-config.xml"},则 TestContext 框架会加载相应的 ApplicationContext,并将其存储在基于这些位置生成的键所标识的 static 上下文缓存中。因此,如果 TestClassB 也为其位置定义了 {"app-config.xml", "test-config.xml"}(无论是显式定义还是通过继承隐式定义),但未定义 @WebAppConfiguration、不同的 ContextLoader、不同的激活配置文件、不同的上下文初始化器、不同的上下文定制器、不同的测试或动态属性源,或不同的父上下文,那么这两个测试类将共享同一个 ApplicationContext。这意味着加载应用上下文的设置开销仅会产生一次(每个测试套件),后续的测试执行将更加快速。
|
测试套件与分叉进程
Spring TestContext 框架将应用程序上下文存储在静态缓存中。这意味着上下文实际上是存储在一个 为了利用缓存机制,所有测试必须在同一个进程或测试套件中运行。这可以通过在 IDE 中将所有测试作为一个组执行来实现。同样,当使用 Ant、Maven 或 Gradle 等构建框架执行测试时,务必确保构建框架不会在测试之间派生新进程。例如,如果 Maven Surefire 插件的 |
上下文缓存的大小是有界的,默认最大大小为 32。每当达到最大大小时,将使用最近最少使用(LRU)驱逐策略来驱逐并关闭过期的上下文。您可以通过设置名为 spring.test.context.cache.maxSize 的 JVM 系统属性,从命令行或构建脚本中配置最大大小。或者,您也可以通过
SpringProperties 机制设置相同的属性。
由于在给定的测试套件中加载大量应用上下文会导致该套件运行时间不必要地延长,因此通常有必要确切了解已加载并缓存了多少个上下文。要查看底层上下文缓存的统计信息,可以将 org.springframework.test.context.cache 日志类别设置为 DEBUG 级别。
在极少数情况下,如果某个测试破坏了应用程序上下文并需要重新加载(例如,通过修改 Bean 定义或应用程序对象的状态),您可以在测试类或测试方法上添加 @DirtiesContext 注解(参见
Spring 测试注解 中关于 ../../annotations/integration-spring/annotation-dirtiescontext.html 的讨论)。
这将指示 Spring 从缓存中移除该上下文,并在运行下一个需要相同应用程序上下文的测试之前重新构建应用程序上下文。请注意,对 @DirtiesContext 注解的支持由
DirtiesContextBeforeModesTestExecutionListener 和
DirtiesContextTestExecutionListener 提供,这两个监听器默认是启用的。
|
ApplicationContext 生命周期与控制台日志
当你需要调试使用 Spring TestContext 框架执行的测试时,分析控制台输出(即输出到 关于由 Spring 框架自身或在 测试的 测试的
如果在某个测试方法执行后,根据 当 Spring |