1

在深入了解 spring TestContext 配置期间,我遇到了 spring-boot-test 问题。

示例项目:github示例项目

我有三个带有一些 bean 的 Spring 配置(Config1- 重量级配置,我需要缓存它)

@ContextHierarchy在上下文中用于单独的配置,并且我希望 Config1 只会加载一次。(使用 @ContextHierarchy 因为我在 spring-boot-test 中没有找到类似物)

完整代码:

@ContextHierarchy({
    @ContextConfiguration(classes = {Config1.class}),
    @ContextConfiguration(classes = {Config2.class}),
})

如果我运行测试,Config1 真的被缓存了!但是,我看到以下内容:

Started ConfigTest1

两次和

Started ConfigTest2

只有一次。在我看来,这是可能的,因为ConfigTest1已经缓存为 TestContext (它发生了,因为ConfigTest1ConfigTest2包含在同一个包中)

这意味着 spring 启动了我的 spring 上下文三遍!为什么?在日志中看到 spring boot logo 三次:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: 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 真的会被缓存!在这种情况下——没有缓存

4

1 回答 1

1

一切正常!

您只是感到困惑,因为 Spring Boot 记录了为其ApplicationContext加载的测试类的名称。因此,您会ConfigTest1在日志中看到两次,因为为该测试类加载了两个上下文。

如果添加logging.level.org.springframework.test.context.cache=debugapplication.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]

因此,实际上只加载了三个上下文,即您期望的三个。

于 2017-03-29T07:44:06.707 回答