I am writing an integration test for Spring Boot application. All goes well as long as I'm using 100% runtime configuration for the test. But when I'm trying to provide just one custom bean for the bean, everything breaks.
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CombinedControllerIntegrationTest2 {
@TestConfiguration
static class ContextConfiguration {
@Bean
@Primary
public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() {
LOG.debug("SolrDocumentTypeMapRepository is being initialized.");
// etc.
code variant above is causing the real, runtime SolrDocumentTypeMapRepository to load. ContextConfiguration in my test class is ignored.
If I try to use @Configuration instead of @TestConfiguration on my inner ContextConfiguration, execution falls to another extreme - it ends with
org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
Because, apparently, the rest of configuration is not loaded.
If I try to put
@ContextConfiguration(classes = {CombinedControllerIntegrationTest2.ContextConfiguration.class,GatewayApplication.class})
on my main testing class, it fails the same way as in #1 - i.e. my ContextConfiguration is ignored.
Any ideas?
P.S. I know I can use @MockBean (and this even works in other cases), but here, because at some point I have dependency on @PostConsruct methods in the main code, @MockBeans are useless.
Unit Test with One Bean
Just use @RunWith(SpringRunner.class)
annotation, it should work. You can also use @RunWith(SpringJUnit4ClassRunner.class)
. Both should work.
Please don't use @SpringBootTest
annotation. It will wire up the whole application.
Here is your updated example,
@RunWith(SpringRunner.class)
public class CombinedControllerIntegrationTest2 {
@TestConfiguration
static class ContextConfiguration {
@Bean
public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() {
LOG.debug("SolrDocumentTypeMapRepository is being initialized.");
return new SolrDocumentTypeMapRepository(...);
}
}
@Autowired
private SolrDocumentTypeMapRepository repository;
@Test
public void test() {
assertNotNull(repository);
}
}
Integration Test with a Replaced Bean
Create a new test Spring Boot application. It should exclude the configuration class (for e.g.,
SolrConfiguration
) which is responsible for creatingSolrDocumentTypeMapRepository
bean.@SpringBootApplication @ComponentScan(basePackages = { "com.abc.pkg1", "com.abc.pk2"}, excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = SolrConfiguration.class)}) public class TestApplication { public static void main(String[] args) throws Exception { SpringApplication.run(TestApplication.class, args); } }
Now, use the
@ContextConfiguration
annotation in your test class to add theTestApplication.class
and theContextConfiguration.class
. This will wire up your application with the all the required beans including the replaced bean. Shown below is the updated test class,@ActiveProfiles("test") @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = {TestApplication.class, CombinedControllerIntegrationTest2.ContextConfiguration.class}) public class CombinedControllerIntegrationTest2 { @TestConfiguration static class ContextConfiguration { @Bean public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() { LOG.debug("SolrDocumentTypeMapRepository is being initialized."); return new SolrDocumentTypeMapRepository(...); } } ... }