I am testing a Spring Boot application. I have several test classes, each of which needs a different set of mocked or otherwise customized beans.
Here is a sketch of
You may use additional explicit profiles to avoid such test configurations to be picked up (as suggested in another answer). I also did it and even created some library support for that.
However, Spring-Boot is clever and it has a built-in "type filter" to resolve this issue automatically. For this to work, you need to remove your @ComponentScan
annotation, which would find your test configurations, and let the @SpringBootApplication
do the work. In your example, just remove this:
@SpringBootApplication
@ComponentScan(
basePackageClasses = {
MyApplication.class,
ImportantConfigurationFromSomeLibrary.class,
ImportantConfigurationFromAnotherLibrary.class})
and replace it with:
@SpringBootApplication(scanBasePackageClasses= {
MyApplication.class,
ImportantConfigurationFromSomeLibrary.class,
ImportantConfigurationFromAnotherLibrary.class})
You may also need to annotate your test as @SpringBootTest
. This should avoid auto-scanning any inner-class configurations (and components) except for those residing in the current test.
The following should help you to achieve your goal by introducing a new fake-communication
profile that is applicable only to the current test class.
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles({"test", "fake-communication"})
public class Component1TestWithFakeCommunication {
// @Autowired ...
@Profile("fake-communication")
@Configuration
static class ContextConfiguration {
@Bean
@Primary
public ServiceClient mockedServiceClient() {
return mock(ServiceClient.class);
}
}
}
I would do a couple of things:
@ComponentScan
ing them.Component1TestWithFakeCommunication
, change @SpringApplicationConfiguration(classes = MyApplication.class)
to @SpringApplicationConfiguration(classes = {MyApplication.class, Component1TestWithFakeCommunication.ContextConfiguration.class})
That should give Spring sufficient information to mock up the test beans, but it should prevent the runtime ApplicationContext
from noticing your test beans as well.
If you have a @SpringBootTest
you can just annotate the service you want to mock with @MockBean
. As simple as that.