Reputation: 3370
In my Spring Boot test I'm using 2 mock beans with different qualifiers:
@RunWith(SpringRunner.class)
@SpringBootTest
class HohoTest {
@MockBean @Qualifier("haha") IHaha ahaha;
@MockBean @Qualifier("hoho") IHaha ohoho;
}
Since I'm not using these beans explicitly, I would rather move them away from the class body, as the @MockBean
annotation is now repeatable:
@RunWith(SpringRunner.class)
@SpringBootTest
@MockBean(IHaha.class)
@MockBean(IHaha.class)
class HohoTest {}
However, I need to pass in a qualifier as well, since they have the same type. Any idea on how I can achieve that?
Upvotes: 23
Views: 31162
Reputation: 701
This should now work
@SpringBootTest(
classes = Some.class
)
@MockBean(name = BEAN_NAME, classes = TheBeanClass.class)
@MockBean(name = BEAN_NAME_2, classes = TheBeanClass.class)
class SomeTest {
private final Some some;
@Autowired
SomeTest(Some some) {
this.some = some;
}
}
Please note, if you need to use any of the mocked beans, you will have to put the @Qualifier in the constructor, for example
private final TheBeanClass theBeanclass;
private final Some some;
@Autowired
SomeTest(Some some, @Qualifier(BEAN_NAME) TheBeanClass theBeanClass) {
this.some = some;
this.theBeanClass = theBeanClass;
}
Upvotes: 2
Reputation: 3736
Because using annotation @Qualifier
means choose bean by name, so you can set up a name for a mock with code like this:
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {JsonMapperConfig.class})
public class IntegrationFlowTest {
@MockBean(name = "s3MessageRepository")
private S3Repository s3MessageRepository;
// etc
Upvotes: 24
Reputation: 1838
I had a similar requirement of injecting mocked service beans with @Order annotation. I also needed to verify the invocation count of service functions. Below is my implementation. It might help someone.
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceNameTest {
@Autowired private ServiceName serviceName;
// Important: Used to reset interaction count of our static
// bean objects before every test.
@Before
public void reset_mockito_interactions() {
Mockito.clearInvocations(MockServicesConfig.bean1);
Mockito.clearInvocations(MockServicesConfig.bean2);
}
@Configuration
public static class MockServicesConfig {
public static InterfaceName bean1;
public static InterfaceName bean2;
@Bean
@Order(1)
public InterfaceName bean1() {
bean1 = Mockito.mock(InterfaceName.class);
// Common when() stubbing
return bean1;
}
@Bean
@Order(2)
public InterfaceName vmpAdapter() {
bean2 = Mockito.mock(InterfaceName.class);
// Common when() stubbing
return bean2;
}
}
@Test
public void test_functionName_mock_invocation1() {
// Arrange --> Act --> Assert
// nullify other functions custom when() stub.
// updating this functions custom when() stub.
verify(MockServicesConfig.bean1, times(1)).functionName("");
}
@Test
public void test_functionName_mock_invocation2() {
// Arrange --> Act --> Assert
// nullify other functions custom when() stub.
// updating this functions custom when() stub.
verify(MockServicesConfig.bean1, times(1)).functionName("");
}
}
Upvotes: 1
Reputation: 11723
If it is okay to move the mock definition completely out of the test class, you could also create the mocks in a separate @Configuration
class:
@Configuration
public class MockConfiguration
{
@Bean @Qualifier("haha")
public IHaha ahaha() {
return Mockito.mock(IHaha.class);
}
@Bean @Qualifier("hoho")
public IHaha ohoho() {
return Mockito.mock(IHaha.class);
}
}
Upvotes: 6
Reputation: 31227
When declaring @MockBean
at the class level, there is currently no support for providing a qualifier.
If you would like to have such support, I suggest you request it in the Spring Boot issue tracker.
Otherwise, you will need to continue declaring @MockBean
on fields alongside @Qualifier
.
Upvotes: 6