Reputation: 123
I have an issue with spring-boot-test during deep dive in spring TestContext configuration.
Example project: github example project
I have three Spring configurations with some beans (Config1
- heavyweight config, and I need to cache it)
I use @ContextHierarchy
for separate configs in the context, and I expect that Config1 will be loaded only once. (Used @ContextHierarchy because I did not find an analogue in spring-boot-test)
Full code:
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config2.class}),
})
If I run the test, the Config1 was really cached! However, I see the following:
Started ConfigTest1
Two times And
Started ConfigTest2
Only once. In my opinion, it is possible because ConfigTest1
already cached as TestContext (it happens, because ConfigTest1
and ConfigTest2
contained in the same package)
That means spring boot up my spring context three times! Why? See spring boot logo three times in log:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.2.RELEASE)
What do you mean about this behaviour? Is it a bug or a feature? Maybe I do something wrong?
Update1:
Thanks a lot. However, if i set properties (or classes) in @SpringBootTest in different order in two test classes – no configuration will be cached :(
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config2.class}),
})
public class ConfigTest1 {
and
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "property1=1")
@ContextHierarchy({
@ContextConfiguration(classes = {Config1.class}),
@ContextConfiguration(classes = {Config3.class}),
})
public class ConfigTest2 {
In case there is no properties – config1 really will be cached! And in this case – nothing cached
Upvotes: 2
Views: 3694
Reputation: 31177
Everything is working as it should!
You're just confused because of the fact that Spring Boot logs the name of the test class for which the ApplicationContext
was loaded. Thus, you see ConfigTest1
twice in the log, because two contexts are loaded for that test class.
If you add logging.level.org.springframework.test.context.cache=debug
to application.properties
, you'll see the following log output.
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]
Thus, there are in fact only three contexts loaded, namely the three you expect.
Upvotes: 1