问题描述
我有一个带有两个实现的接口。使用哪种实现取决于环境(生产、开发、测试等)。因此,我使用 Spring 配置文件。我正在使用配置文件来实例化正确的实现。
@Configuration
public class BeanConfiguration {
@Profile({"develop","test-unit"})
@Bean(name = "customerEmailSender")
public CustomerEmailSender emailSenderImpl_1(){
return new EmailSenderImpl_1();
}
@Profile({"prod"})
@Bean(name = "customerEmailSender")
public CustomerEmailSender emailSenderImpl_2(){
return new EmailSenderImpl_2();
}
}
当 Spring 容器启动时(具有特定配置文件),正确的 bean 会自动装配到类中,并且一切正常。
@Component
public class CustomerEmailProcessor {
@Autowire
private CustomerEmailSender customerEmailSender;
...
}
我还有一个测试类,我想在其中自动装配 bean。我正在使用@Mock 进行自动装配。
配置文件在测试类中设置为“test-unit”。所以,我期待 spring 容器在配置类中查找要实例化的正确 bean。但这不会发生。
相反,抛出异常:
引起:java.lang.IllegalStateException:无法注册模拟 bean .... 期望替换单个匹配 bean,但发现 [customerEmailSender,emailSenderImpl_1,emailSenderImpl_2]
使用@Autowire 注释时,一切正常。但当然,bean 不再被嘲笑了,这就是我需要的。
@RunWith(springrunner.class)
@ActiveProfiles(profiles = {"test-unit"})
@Import(BeanConfiguration.class)
public class CustomerEmailResourceTest {
@MockBean
private CustomerEmailSender customerEmailSender;
}
我在配置类中放置了一个断点,我可以看到在测试类中使用@Autowire 时,正确的 bean 被实例化(在“return new EmailSenderImpl_1();”行中断。 使用@Mock 时,根本不会实例化任何 bean。 Spring 不会在“return new EmailSenderImpl_1();”行中断。
为什么Spring使用@Mock注解可以找到正确的bean。
解决方法
@Mock 注解一定是 Spring 不使用配置类“BeanConfiguration.java”的原因。毕竟这是有道理的。