I have a @SpringBootTest
class that has a rather complex mock definition setup with mocked return values.
Question: can I externalize @MockBean
setups into an own class, so I could reuse the mock configuration in multiple class (sidenote: I'm not looking for inheritance here!).
@SpringBootTest
public class ServiceTest extends DefaultTest {
@Autowired
private ServiceController controller;
@MockBean
private Service1 s1;
@MockBean
private Service2 s2;
@MockBean
private Service3 s3;
//assume more complex mock definitions
@BeforeEach
public void mock() {
when(s1.invoke()).thenReturn(result1);
when(s2.invoke()).thenReturn(result2);
when(s3.invoke()).thenReturn(result3);
}
@Test
public void test() {
//...
}
}
I want to load the mocks independently of each other, not globally for all my tests.
We can use the @MockBean to add mock objects to the Spring application context. The mock will replace any existing bean of the same type in the application context. If no bean of the same type is defined, a new one will be added.
@MockBean: ( org.springframework.boot.test.mock.mockito.MockBean ) Annotation that can be used to add mocks to a Spring ApplicationContext. Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner.
The @MockBean is a Spring Boot test annotation that is used to add mocks to ApplicationContext . 2. A mock will replace existing bean of the same type defined in the context and if no existing bean then new one will be added to context. 3. The @MockBean can be used at field level and class level in unit test classes.
@MockBean annotation It can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner. Any existing single bean of the same type defined in the context will be replaced by the mock. If no existing bean is defined a new one will be added.
Not directly what you are asking for, but one possibility is to not use @MockBean
but instead define your reusable mocks as @Primary
@Bean
s in multiple @TestConfiguration
s that you can selectively @Import
in your tests:
@TestConfiguration
public class MockService1 {
@Bean
@Primary
public Service1 service1Mock() {
Service1 s1 = Mockito.mock(Service1.class);
when(s1.invoke()).thenReturn("result1");
return s1;
}
}
There's a nice article about this approach: Building Reusable Mock Modules with Spring Boot.
Just for reference (if the @TestConfiguration
approach might not be suitable for whatever reason), it also works when creating a junit Extension
:
public class MockService1Extension implements BeforeTestExecutionCallback {
@Override
public void beforeTestExecution(ExtensionContext extensionContext) throws Exception {
ApplicationContext springContext = SpringExtension.getApplicationContext(extensionContext);
Service1 s1 = springContext.getBean(Service1.class);
when(s1.invoke()).thenReturn("result1");
}
}
@ExtendWith(MockService1Extension1.class)
@MockBean({Service1.class})
public class TestImpl {
@Test
public void test() {
}
}
Unfortunately, for this approach, the implementing test must list the beans mocked inside the extension additionally with @MockBean
on class level.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With