【问题标题】:Is it possible to cache Spring's Application Context between classes?是否可以在类之间缓存 Spring 的应用程序上下文?
【发布时间】:2018-02-14 01:56:01
【问题描述】:

我正在尝试提高我正在处理的项目的 Spring 集成测试的性能。我们正在使用 Spring + Gradle + JUnit。

build.gradle 文件中使用此配置:

test {
    useJUnit()
    setForkEvery(0)
    setMaxParallelForks(1)
}

我们能够在单个 JVM 中运行所有测试。虽然我认为这是默认行为。

但我一直在阅读有关 Spring Test Context Caching 以及我的 application-test.yml 中的此属性:

logging:
  level:
    org:
      springframework:
        test:
          context:
            cache: DEBUG

我注意到在同一类中运行的测试方法的以下日志

2017-09-05 08:33:11.829 DEBUG 5764 --- [    Test worker] c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [THIS HAD SENSITIVE DATA]
2017-09-05 08:33:11.830 DEBUG 5764 --- [    Test worker] org.springframework.test.context.cache   : Spring test ApplicationContext cache statistics: [DefaultContextCache@572e81e7 size = 1, maxSize = 32, parentContextCount = 0, hitCount = 0, missCount = 1]
2017-09-05 08:33:11.849 DEBUG 5764 --- [    Test worker] c.DefaultCacheAwareContextLoaderDelegate : Retrieved ApplicationContext from cache with key [THIS HAD SENSITIVE DATA]
2017-09-05 08:33:11.850 DEBUG 5764 --- [    Test worker] org.springframework.test.context.cache   : Spring test ApplicationContext cache statistics: [DefaultContextCache@572e81e7 size = 1, maxSize = 32, parentContextCount = 0, hitCount = 1, missCount = 1]

还有很多行写着Retrieved ApplicationContext from cache with key...

对于在其他类中运行的测试方法,我注意到类似的日志,例如:

2017-09-05 08:33:12.971 DEBUG 10288 --- [    Test worker] c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [THIS HAD SENSITIVE DATA]
2017-09-05 08:33:12.971 DEBUG 10288 --- [    Test worker] org.springframework.test.context.cache   : Spring test ApplicationContext cache statistics: [DefaultContextCache@2dad6721 size = 1, maxSize = 32, parentContextCount = 0, hitCount = 0, missCount = 1]
2017-09-05 08:33:13.194 DEBUG 10288 --- [    Test worker] c.DefaultCacheAwareContextLoaderDelegate : Retrieved ApplicationContext from cache with key [THIS HAD SENSITIVE DATA]
2017-09-05 08:33:13.194 DEBUG 10288 --- [    Test worker] org.springframework.test.context.cache   : Spring test ApplicationContext cache statistics: [DefaultContextCache@2dad6721 size = 1, maxSize = 32, parentContextCount = 0, hitCount = 1, missCount = 1]

两个类的注释是一样的:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles({"default", "profile-1", "profile-2"})
public class SomeControllerTest {

    // Test methods...
}

我认为两个类中的测试方法应该可以共享相同的ApplicationContext,从而减少测试持续的时间。但是,有可能做到吗?如果有,怎么做?

我注意到ApplicationContext 两个对象几乎同时存储在缓存中08:33:11.82908:33:12.971。 Test Runner 是否在不同的线程中执行测试?

【问题讨论】:

  • 您是否有机会使用@MockBean@SpyBean
  • 我们没有使用@SpyBean,但是我们使用了一些@MockBean注解,这些注解在不同的控制器测试类之间是不同的……你认为是这个原因吗?

标签: spring gradle junit spring-test applicationcontext


【解决方案1】:

您的上下文实际上已被缓存,但由于您使用 Spring Boot 的 @MockBean 功能,因此您实际上拥有两个不同的上下文。

@MockBean 的使用导致每个 ApplicationContext 具有不同的唯一键,在该键下它存储在上下文缓存中。

虽然这可能不会在任何地方公开记录,但实际上在 org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory 的实现中有内嵌文档:

我们在这里收集显式模拟定义,因为它们构成 MergedContextConfiguration 键的一部分。不同的模拟需要有不同的键。

我已针对 Spring Boot 提出问题以记录此行为:https://github.com/spring-projects/spring-boot/issues/10182

【讨论】:

  • 我认为@MockBean 会创建单独的上下文,但是如果我使用@SpyBean 呢?那还行吗?
  • 在我的例子中,@MockBean@SpyBean 的类导致上下文根本不共享!
猜你喜欢
  • 2011-08-29
  • 1970-01-01
  • 2014-02-21
  • 1970-01-01
  • 2015-07-13
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
相关资源
最近更新 更多