Spring 为什么@MockBean 不能使用配置文件自动装配接口

问题描述

我有一个带有两个实现的接口。使用哪种实现取决于环境(生产、开发、测试等)。因此,我使用 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”的原因。毕竟这是有道理的。