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.
Bean Overriding Spring beans are identified by their names within an ApplicationContext. Therefore, bean overriding is a default behavior that happens when we define a bean within an ApplicationContext that has the same name as another bean. It works by simply replacing the former bean in case of a name conflict.
This can be done without restarting the application at runtime when Loading and Removing bean in Spring Application. If the client code needs to register objects which are not managed by Spring container, then we will need to work with an instance of BeanDefinition. Here, We have used the following dependencies.
Annotation Type SpringBootApplication. Indicates a configuration class that declares one or more @Bean methods and also triggers auto-configuration and component scanning . This is a convenience annotation that is equivalent to declaring @Configuration , @EnableAutoConfiguration and @ComponentScan .
Annotating a class with the @Configuration annotation indicates that the class will be used by JavaConfig as a source of bean definitions. An application may make use of just one @Configuration -annotated class, or many. @Configuration can be considered the equivalent of XML's <beans/> element.
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);
}
}
Create a new test Spring Boot application. It should exclude the configuration class (for e.g., SolrConfiguration
) which is responsible for creating SolrDocumentTypeMapRepository
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 the TestApplication.class
and the ContextConfiguration.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(...);
}
}
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With