user2023141
user2023141

Reputation: 1223

Spring why @MockBean can't autowire an interface using profile

I've an interface with two implementations. Which implementaton is to be used depends of the environment (production, development, test, ...). I therefore use Spring profiles. I'm using a configuration file to instantiate the correct implementation.

@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();
    }
}

When the Spring container starts (with a specific profile), the correct bean is autowired into the class, and all works fine.

@Component
public class CustomerEmailProcessor {

    @Autowire
    private CustomerEmailSender customerEmailSender;
    
    ...
}

I also have a test class in which I want to autowire the bean. I'm using @Mock for autowiring. The profile is set to "test-unit" in the test class. So, I'm expecting the spring container to lookup in the config class for the correct bean to be instantiated. But this doesn't happen. Instead, an Exception is thrown :
Caused by: java.lang.IllegalStateException: Unable to register mock bean .... expected a single matching bean to replace but found [customerEmailSender, emailSenderImpl_1, emailSenderImpl_2]

When using @Autowire annotation, all goes fine. But of course the bean is not mocked anymore and that's what I need to have.

@RunWith(SpringRunner.class)
@ActiveProfiles(profiles = {"test-unit"})
@Import(BeanConfiguration.class)
public class CustomerEmailResourceTest {

    @MockBean
    private CustomerEmailSender customerEmailSender;
    
}

I've put a breakpoint in the config class, and I can see that when using @Autowire in the test class, the correct bean is instantiated (breaks at the line "return new EmailSenderImpl_1();". When using @Mock, no bean at all is instantiated. Spring doesn't break at the line "return new EmailSenderImpl_1();"

Why is it that Spring can find the correct bean when using the @Mock annotation.

Upvotes: 0

Views: 1450

Answers (1)

user2023141
user2023141

Reputation: 1223

The @Mock annotation must be the reason that Spring doesn't use the config class "BeanConfiguration.java". That makes sence after all.

Upvotes: 0

Related Questions