在测试中自发启动 spring 启动上下文
Spontaneous up spring boot context in test
我在深入研究 spring TestContext 配置时遇到 spring-boot-test 问题。
我有三个 Spring 配置和一些 bean(Config1
- 重量级配置,我需要缓存它)
我在上下文中使用 @ContextHierarchy
作为单独的配置,我希望 Config1 只会加载一次。 (使用@ContextHierarchy 因为我没有在 spring-boot-test 中找到类似物)
完整代码:
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config2.class}),
})
如果我运行测试,Config1真的被缓存了!但是,我看到以下内容:
Started ConfigTest1
两次
并且
Started ConfigTest2
只有一次。在我看来,这是可能的,因为 ConfigTest1
已经缓存为 TestContext(它发生了,因为 ConfigTest1
和 ConfigTest2
包含在同一个包中)
这意味着 spring 启动我的 spring 上下文三次!为什么?
在日志中看到spring三次开机标志:
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.2.RELEASE)
这种行为是什么意思?这是错误还是功能?也许我做错了什么?
更新1:
非常感谢。但是,如果我在两个测试 类 中以不同的顺序在 @SpringBootTest 中设置属性(或 类)——不会缓存任何配置 :(
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config2.class}),
})
public class ConfigTest1 {
和
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "property1=1")
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config3.class}),
})
public class ConfigTest2 {
如果没有属性 – config1 真的会被缓存!在这种情况下——没有缓存
一切正常!
您只是感到困惑,因为 Spring Boot 记录了加载 ApplicationContext
的测试 class 的名称。因此,您会在日志中看到两次 ConfigTest1
,因为为该测试加载了两个上下文 class.
如果将 logging.level.org.springframework.test.context.cache=debug
添加到 application.properties
,您将看到以下日志输出。
DEBUG ... c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [[WebMergedContextConfiguration@7a765367 testClass = ConfigTest1, locations = '{}', classes = '{class spring.test.mistake.delete.Config1}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]]
DEBUG ... c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [[WebMergedContextConfiguration@52feb982 testClass = ConfigTest1, locations = '{}', classes = '{class spring.test.mistake.delete.Config2}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [WebMergedContextConfiguration@7a765367 testClass = ConfigTest1, locations = '{}', classes = '{class spring.test.mistake.delete.Config1}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]]]
DEBUG ... c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [[WebMergedContextConfiguration@5ddcc487 testClass = ConfigTest2, locations = '{}', classes = '{class spring.test.mistake.delete.Config3}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [WebMergedContextConfiguration@44c73c26 testClass = ConfigTest2, locations = '{}', classes = '{class spring.test.mistake.delete.Config1}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]]]
DEBUG ... org.springframework.test.context.cache : Spring test ApplicationContext cache statistics: [DefaultContextCache@478db956 size = 3, maxSize = 32, parentContextCount = 1, hitCount = 11, missCount = 3]
因此,实际上只加载了三个上下文,即您期望的三个。
我在深入研究 spring TestContext 配置时遇到 spring-boot-test 问题。
我有三个 Spring 配置和一些 bean(Config1
- 重量级配置,我需要缓存它)
我在上下文中使用 @ContextHierarchy
作为单独的配置,我希望 Config1 只会加载一次。 (使用@ContextHierarchy 因为我没有在 spring-boot-test 中找到类似物)
完整代码:
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config2.class}),
})
如果我运行测试,Config1真的被缓存了!但是,我看到以下内容:
Started ConfigTest1
两次 并且
Started ConfigTest2
只有一次。在我看来,这是可能的,因为 ConfigTest1
已经缓存为 TestContext(它发生了,因为 ConfigTest1
和 ConfigTest2
包含在同一个包中)
这意味着 spring 启动我的 spring 上下文三次!为什么? 在日志中看到spring三次开机标志:
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.2.RELEASE)
这种行为是什么意思?这是错误还是功能?也许我做错了什么?
更新1:
非常感谢。但是,如果我在两个测试 类 中以不同的顺序在 @SpringBootTest 中设置属性(或 类)——不会缓存任何配置 :(
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config2.class}),
})
public class ConfigTest1 {
和
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "property1=1")
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config3.class}),
})
public class ConfigTest2 {
如果没有属性 – config1 真的会被缓存!在这种情况下——没有缓存
一切正常!
您只是感到困惑,因为 Spring Boot 记录了加载 ApplicationContext
的测试 class 的名称。因此,您会在日志中看到两次 ConfigTest1
,因为为该测试加载了两个上下文 class.
如果将 logging.level.org.springframework.test.context.cache=debug
添加到 application.properties
,您将看到以下日志输出。
DEBUG ... c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [[WebMergedContextConfiguration@7a765367 testClass = ConfigTest1, locations = '{}', classes = '{class spring.test.mistake.delete.Config1}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]]
DEBUG ... c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [[WebMergedContextConfiguration@52feb982 testClass = ConfigTest1, locations = '{}', classes = '{class spring.test.mistake.delete.Config2}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [WebMergedContextConfiguration@7a765367 testClass = ConfigTest1, locations = '{}', classes = '{class spring.test.mistake.delete.Config1}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]]]
DEBUG ... c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [[WebMergedContextConfiguration@5ddcc487 testClass = ConfigTest2, locations = '{}', classes = '{class spring.test.mistake.delete.Config3}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [WebMergedContextConfiguration@44c73c26 testClass = ConfigTest2, locations = '{}', classes = '{class spring.test.mistake.delete.Config1}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.SpringBootTestContextCustomizer@643b1d11, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6d00a15d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@475530b9], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]]]
DEBUG ... org.springframework.test.context.cache : Spring test ApplicationContext cache statistics: [DefaultContextCache@478db956 size = 3, maxSize = 32, parentContextCount = 1, hitCount = 11, missCount = 3]
因此,实际上只加载了三个上下文,即您期望的三个。