Reputation: 279
In my spring boot application I have a service bean (with @Service annotation) and I want to mock this service in particular JUnit test (not in all tests). How can I replace this service bean for just one particular test?
Service declared as:
@Service
public class LocalizationServiceImpl implements LocalizationService {
...
}
App configuration class:
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages="my.package")
@EntityScan
public class Application {
...
}
Test class:
@Transactional
@SpringApplicationConfiguration(classes = LocalizationServiceTest.LocalizationServiceTestConfig.class)
public class LocalizationServiceTest extends ESContextTest {
@Autowired
private LocalizationService locService;
@Configuration
public static class LocalizationServiceTestConfig {
@Bean
public LocalizationService localizationServiceImpl() {
return mock(LocalizationService.class);
}
}
}
And test class parent:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public abstract class ESContextTest {
...
}
But this does not work. When I run the test then original LocalizationServiceImpl is used for autowired locService property. This appeared in log file: Skipping bean definition for [BeanMethod:name=localizationService,declaringClass=...LocalizationServiceTest$LocalizationServiceTestConfig]: a definition for bean 'localizationService' already exists. This top-level bean definition is considered as an override.
When I use different name for @Bean method in LocalizationServiceTestConfig e.g. localizationServiceMock() (to be different from original implementation classname) then spring throws
'No qualifying bean of type is defined: expected single matching bean but found 2: localizationServiceImpl,localizationServiceMock'
So I thought it is correct to use the same name.
Only working solution is to remove @Service annotation from LocalizationServiceImpl class and create configuration for normal (not test) app run like
@Configuration
public class BeansConfig {
@Bean
public LocalizationService localizationServiceImpl() {
return new LocalizationServiceImpl();
}
}
Then in test run the correct mock implementation is autowired.
But it should be possible to do the same via @Service annotation, shouldn't?
Thanks for advice.
Upvotes: 9
Views: 3836
Reputation: 279
Found a solution by myself: rename localizationServiceImpl()
e.g. to localizationServiceMock()
in class LocalizationServiceTestConfig
and annotate the method with @Primary
.
But why simply redefining bean with the same 'id' doesn't work like via xml-config?
Upvotes: 12