4 Expiriments on @SpringBootTest context sharing
I faced a problem in my relatively new project which the Test Spring Context failed to share across different integration tests. I have an abstract class with @SpringBootTest annotation and subclasses extending this abstract class I don’t have @TestInstance(PER_CLASS) or @DirtyContext configuration but my @TestConfiguration class is created in every test. Since I have an embedded kafka server inside the TestConfiguration
Experiment 1
2 tests extending the same BaseIntegrationTest.
@ExtendWith(SpringExtension::class)
@SpringBootTest
@Import(TestProducer::class, KafkaTestConfig::class)
class BaseIntegrationTest {
}
@TestConfiguration
class KafkaTestConfig {
@Bean
fun testKafkaServer() {
EmbeddedKafkaBroker(1, true, 1).also {
it
.kafkaPorts(9092)
.afterPropertiesSet()
}
}
}
The testKafkaServer bean only initialized once
Experiment 2
Use @DirtyContext
@ExtendWith(SpringExtension::class)
@SpringBootTest
@Import(TestProducer::class, KafkaTestConfig::class)
@DirtiesContext
class BaseIntegrationTest {
}
The testKafkaServer bean initialized between tests
Experiment 3
Use @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class KafkaConsumerTest : BaseIntegrationTest() {
...
}
@ExtendWith(SpringExtension::class)
@SpringBootTest
@Import(TestProducer::class, KafkaTestConfig::class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class BaseIntegrationTest {
}
No issues observed in this setup, increase timeout to 10 seconds
Experiment 4
use different folder structure in test folder No issues even if I put the folder under a separate integrationTests folder, as long as it has the same root path as SpringBootApplication.kt
Conclusion
In my project, it seems the injection of mockbean which supposed to replace the actual bean in the spring test context did not happen occasionally during the integration. I could not figure out why it fails. Eventually, I stooped using @MockBean annotation and manually create a @TestConfiguration with @Bean to create the objects
In the @Configuration, I use @Profile(“!test”) to disable the loading of actual bean into context during testing