Spring Boot Integration Testing with mocked Services/Components
When you annotate a field with @MockBean, spring will create a mock of the annotated class and use it to autowire all beans of the application context.
You must not create the mock yourself with
Settings settings = Mockito.mock(Settings.class);
this would create a second mock, leading to the described problem.
Solution :
@MockBean
private Settings settings;
@Before
public void before() {
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
}
@Test
public void contextLoads() {
String applicationsecret = settings.getApplicationSecret();
System.out.println("Application secret: " + applicationsecret);
}
Looks like you are using Settings object before you specify its mocked behavior. You have to run
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
during configuration setup. For preventing that you can create special configuration class for test only.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MyApplication.class, MyApplicationTest.TestConfig.class})
public class MyApplicationTest {
private static final String SECRET = "Application Secret";
@TestConfiguration
public static class TestConfig {
@Bean
@Primary
public Settings settingsBean(){
Settings settings = Mockito.mock(Settings.class);
Mockito.when(settings.getApplicationSecret()).thenReturn(SECRET);
Mockito.doReturn(SECRET).when(settings).getApplicationSecret();
return settings;
}
}
.....
}
Also I would recommend you to use next notation for mocking:
Mockito.doReturn(SECRET).when(settings).getApplicationSecret();
It will not run settings::getApplicationSecret