Reputation: 86757
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.
Upvotes: 6
Views: 3017
Reputation: 86757
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.
Upvotes: 2
Reputation: 3178
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.
Upvotes: 11
Reputation: 758
I think your answer lies here: https://stackoverflow.com/a/50802303/10811865
Create a test profile that implements those MockBeans like so:
@Profile("test")
@Configuration
public class MyMockConfiguration {
@Bean
public SomeService someService() {
SomeService someService = mock(SomeService .class);
// mocked methods and results
return someService ;
}
And then use that profile with these annotations on your test class:
@ActiveProfiles("test")
@SpringBootTest
@WebAppConfiguration
@RunWith(SpringRunner.class)
Upvotes: -1