Context Caching
一旦 TestContext 框架为测试加载了一个 ApplicationContext
(或 WebApplicationContext
),该上下文将被缓存并再次用于同一测试套件内声明相同唯一上下文配置的所有后续测试。要理解缓存如何工作的,理解什么是“唯一
”和“测试套件
”很重要。
Once the TestContext framework loads an ApplicationContext
(or WebApplicationContext
)
for a test, that context is cached and reused for all subsequent tests that declare the
same unique context configuration within the same test suite. To understand how caching
works, it is important to understand what is meant by “unique” and “test suite.”
可以通过用于加载 ApplicationContext
的配置参数的组合来唯一地标识它。因此,用于生成作为缓存上下文密钥的密钥的配置参数的唯一组合。TestContext 框架使用以下配置参数构建上下文缓存密钥:
An ApplicationContext
can be uniquely identified by the combination of configuration
parameters that is used to load it. Consequently, the unique combination of configuration
parameters is used to generate a key under which the context is cached. The TestContext
framework uses the following configuration parameters to build the context cache key:
-
locations
(from@ContextConfiguration
) -
classes
(from@ContextConfiguration
) -
contextInitializerClasses
(from@ContextConfiguration
) -
contextCustomizers
(fromContextCustomizerFactory
) – this includes@DynamicPropertySource
methods as well as various features from Spring Boot’s testing support such as@MockBean
and@SpyBean
. -
contextLoader
(from@ContextConfiguration
) -
parent
(from@ContextHierarchy
) -
activeProfiles
(from@ActiveProfiles
) -
propertySourceDescriptors
(from@TestPropertySource
) -
propertySourceProperties
(from@TestPropertySource
) -
resourceBasePath
(from@WebAppConfiguration
)
例如,如果 TestClassA
为 @ContextConfiguration
的 locations
(或 value
)属性指定 {"app-config.xml", "test-config.xml"}
,则 TestContext 框架将加载相应的 ApplicationContext
,并将其存储在仅根据这些位置的键下的静态上下文缓存中。所以,如果 TestClassB
也为其位置定义 {"app-config.xml", "test-config.xml"}
(显式或隐式通过继承),但没有定义 @WebAppConfiguration
、不同的 ContextLoader
、不同的活动配置文件、不同的上下文初始化程序、不同的测试属性来源或不同的父上下文,那么相同的 ApplicationContext
将由这两个测试类共享。这意味着加载应用程序上下文的设置成本只发生一次(每个测试套件),后续测试执行会快很多。
For example, if TestClassA
specifies {"app-config.xml", "test-config.xml"}
for the
locations
(or value
) attribute of @ContextConfiguration
, the TestContext framework
loads the corresponding ApplicationContext
and stores it in a static
context cache
under a key that is based solely on those locations. So, if TestClassB
also defines
{"app-config.xml", "test-config.xml"}
for its locations (either explicitly or
implicitly through inheritance) but does not define @WebAppConfiguration
, a different
ContextLoader
, different active profiles, different context initializers, different
test property sources, or a different parent context, then the same ApplicationContext
is shared by both test classes. This means that the setup cost for loading an application
context is incurred only once (per test suite), and subsequent test execution is much
faster.
Test suites and forked processes
Spring TestContext 框架将应用程序上下文存储在一个静态缓存中。这意味着上下文从字面上存储在一个 The Spring TestContext framework stores application contexts in a static cache. This
means that the context is literally stored in a 要从缓存机制中受益,所有测试都必须在同一进程或测试套件中运行。这可以通过在 IDE 中将所有测试作为一个组执行来实现。同样,在使用诸如 Ant、Maven 或 Gradle 的构建框架执行测试时,确保构建框架不会在测试之间分叉非常重要。例如,如果 Maven Surefire 插件的 To benefit from the caching mechanism, all tests must run within the same process or test
suite. This can be achieved by executing all tests as a group within an IDE. Similarly,
when executing tests with a build framework such as Ant, Maven, or Gradle, it is
important to make sure that the build framework does not fork between tests. For example,
if the
|
上下文缓存大小受默认最大尺寸32的限制。每当达到最大尺寸时,都会使用最近最少使用(LRU)驱逐策略来驱逐和关闭陈旧的上下文。可以通过设置名为`spring.test.context.cache.maxSize`的JVM系统属性,通过命令行或构建脚本配置最大尺寸。另外,还可以通过SpringProperties
机制设置相同的属性。
The size of the context cache is bounded with a default maximum size of 32. Whenever the
maximum size is reached, a least recently used (LRU) eviction policy is used to evict and
close stale contexts. You can configure the maximum size from the command line or a build
script by setting a JVM system property named spring.test.context.cache.maxSize
. As an
alternative, you can set the same property via the
SpringProperties
mechanism.
由于在给定的测试套件中加载大量的应用程序上下文,可能会导致套件运行时间过长,因此确切地知道已经加载和缓存了多少个上下文通常是有益的。要查看底层上下文缓存的统计信息,您可以将 org.springframework.test.context.cache
日志类别的日志级别设置为 DEBUG
。
Since having a large number of application contexts loaded within a given test suite can
cause the suite to take an unnecessarily long time to run, it is often beneficial to
know exactly how many contexts have been loaded and cached. To view the statistics for
the underlying context cache, you can set the log level for the
org.springframework.test.context.cache
logging category to DEBUG
.
在不太可能发生的情况中,如果一个测试破坏了应用程序上下文并且需要重新加载(例如,通过修改 bean 定义或应用程序对象的 state),您可以使用 `@DirtiesContext`注释您的测试类或测试方法(请参阅 Spring Testing Annotations中对 `@DirtiesContext`的讨论)。这会指示 Spring 从缓存中删除上下文并在运行需要相同应用程序上下文的下一个测试之前重建应用程序上下文。请注意, `@DirtiesContext`注释的支持由 `DirtiesContextBeforeModesTestExecutionListener`和 `DirtiesContextTestExecutionListener`提供,它们默认启用。
In the unlikely case that a test corrupts the application context and requires reloading
(for example, by modifying a bean definition or the state of an application object), you
can annotate your test class or test method with @DirtiesContext
(see the discussion of
@DirtiesContext
in Spring Testing Annotations
). This instructs Spring to remove the context from the cache and rebuild
the application context before running the next test that requires the same application
context. Note that support for the @DirtiesContext
annotation is provided by the
DirtiesContextBeforeModesTestExecutionListener
and the
DirtiesContextTestExecutionListener
, which are enabled by default.
ApplicationContext lifecycle and console logging
当您需要调试使用 Spring TestContext Framework 执行的测试时,分析控制台输出(即,输出到 When you need to debug a test executed with the Spring TestContext Framework, it can be
useful to analyze the console output (that is, output to the 关于由 Spring Framework 本身或在 With regard to console logging triggered by the Spring Framework itself or by components
registered in the 测试的 The 可以通过以下场景之一来关闭测试的 The
如果根据 If the context is closed according to 当通过 JVM 关闭挂钩关闭 Spring When a Spring |