是否可以在 类 之间缓存 Spring 的应用程序上下文?
Is it possible to cache Spring's Application Context between classes?
我正在尝试提高我正在处理的项目的 Spring 集成测试的性能。我们正在使用 Spring + Gradle + JUnit.
在 build.gradle
文件中使用此配置:
test {
useJUnit()
setForkEvery(0)
setMaxParallelForks(1)
}
我们能够 运行 在单个 JVM 中进行所有测试。虽然我认为这是默认行为。
但我一直在阅读有关 Spring Test Context Caching 的文章,并且在我的申请中使用了 属性-test.yml:
logging:
level:
org:
springframework:
test:
context:
cache: DEBUG
我在同一个 class
中注意到测试方法 运行ning 的以下日志
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...
。
对于其他 classes 中的测试方法 运行ning,我注意到类似的日志,例如:
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]
两个 class 的注释相同:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles({"default", "profile-1", "profile-2"})
public class SomeControllerTest {
// Test methods...
}
而且我认为两个 classes 中的测试方法应该可以共享相同的 ApplicationContext
从而减少测试持续的时间。但是,有可能这样做吗?如果是,怎么做?
我注意到 ApplicationContext
个对象大约同时 08:33:11.829
和 08:33:12.971
存储在缓存中。 Test Runner 是否在不同的线程中执行测试?
你的上下文实际上被缓存了,但你实际上有两个不同的上下文,因为你使用 Spring Boot 的 @MockBean
功能。
@MockBean
的使用导致每个 ApplicationContext
有一个不同的 唯一键 ,它存储在上下文缓存中。
虽然这可能不会在任何地方公开记录,但实际上 org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory
的实施中有在线文档:
We gather the explicit mock definitions here since they form part of the MergedContextConfiguration key. Different mocks need to have a different key.
我已经针对 Spring 启动提出了一个问题以记录此行为:https://github.com/spring-projects/spring-boot/issues/10182
我正在尝试提高我正在处理的项目的 Spring 集成测试的性能。我们正在使用 Spring + Gradle + JUnit.
在 build.gradle
文件中使用此配置:
test {
useJUnit()
setForkEvery(0)
setMaxParallelForks(1)
}
我们能够 运行 在单个 JVM 中进行所有测试。虽然我认为这是默认行为。
但我一直在阅读有关 Spring Test Context Caching 的文章,并且在我的申请中使用了 属性-test.yml:
logging:
level:
org:
springframework:
test:
context:
cache: DEBUG
我在同一个 class
中注意到测试方法 运行ning 的以下日志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...
。
对于其他 classes 中的测试方法 运行ning,我注意到类似的日志,例如:
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]
两个 class 的注释相同:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles({"default", "profile-1", "profile-2"})
public class SomeControllerTest {
// Test methods...
}
而且我认为两个 classes 中的测试方法应该可以共享相同的 ApplicationContext
从而减少测试持续的时间。但是,有可能这样做吗?如果是,怎么做?
我注意到 ApplicationContext
个对象大约同时 08:33:11.829
和 08:33:12.971
存储在缓存中。 Test Runner 是否在不同的线程中执行测试?
你的上下文实际上被缓存了,但你实际上有两个不同的上下文,因为你使用 Spring Boot 的 @MockBean
功能。
@MockBean
的使用导致每个 ApplicationContext
有一个不同的 唯一键 ,它存储在上下文缓存中。
虽然这可能不会在任何地方公开记录,但实际上 org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory
的实施中有在线文档:
We gather the explicit mock definitions here since they form part of the MergedContextConfiguration key. Different mocks need to have a different key.
我已经针对 Spring 启动提出了一个问题以记录此行为:https://github.com/spring-projects/spring-boot/issues/10182