在我的 spring boot 应用程序中,我有一个服务 bean(带有 @Service 注释),我想模拟这个服务,特别是 JUnit 测试(不是在所有测试中)。我怎样才能只为一个特定的测试替换这个服务 bean?
服务声明为:
@Service
public class LocalizationServiceImpl implements LocalizationService {
...
}
应用配置类:
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages="my.package")
@EntityScan
public class Application {
...
}
测试类:
@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);
}
}
}
和测试类父类:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public abstract class ESContextTest {
...
}
但这行不通。当我运行测试时,原始 LocalizationServiceImpl 用于 Autowiring 的 locService 属性。这出现在日志文件中: 跳过 [BeanMethod:name=localizationService,declaringClass=...LocalizationServiceTest$LocalizationServiceTestConfig] 的 bean 定义:bean“localizationService”的定义已经存在。此顶级 bean 定义被视为覆盖。
当我在 LocalizationServiceTestConfig 中为 @Bean 方法使用不同的名称时,例如localizationServiceMock() (与原始实现类名不同)然后 spring 抛出
'No qualifying bean of type is defined: expected single matching bean but found 2: localizationServiceImpl,localizationServiceMock'
所以我认为使用相同的名称是正确的。
唯一有效的解决方案是从 LocalizationServiceImpl 类中删除 @Service 注释并为正常(非测试)应用程序运行创建配置,如
@Configuration
public class BeansConfig {
@Bean
public LocalizationService localizationServiceImpl() {
return new LocalizationServiceImpl();
}
}
然后在测试运行中 Autowiring 正确的模拟实现。
但应该可以通过@Service 注释来做同样的事情,不是吗?
感谢您的建议。
最佳答案
自己找到了一个解决方案:重命名localizationServiceImpl()
例如到类 LocalizationServiceTestConfig
中的 localizationServiceMock()
并用 @Primary
注释该方法。
但为什么简单地重新定义具有相同“id”的 bean 不能像通过 xml-config 那样工作?
关于Spring - 在测试中替换@Service bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31836227/