'Creating strict mock when using @MockBean of spring boot?

I use @MockBean of spring boot (with @RunWith(SpringRunner.class)) and everything was ok so far.
However the mock provides default implementation for every method of the mocked class so I cannot check if only those methods were called that I expected to be called, i.e. I would like to create strict mock.
Is that possible with @MockBean?

I don't insist on creating strict mocks if somebody has a good idea how to check if only those methods were called that I expected.

Thanks for the help in advance!

Regards,
V.



Solution 1:[1]

With Mockito you can verify that a method was called:

verify(mockOne).add("one");

or that it was never called (never() is more readable alias for times(0)):

verify(mockOne, never()).remove("two");

Or you can verify that no other method was called:

verify(mockOne).add("one"); // check this one
verifyNoMoreInteractions(mockOne); // and nothing else

For more information see the Mockito documentation.

Solution 2:[2]

You can use Mockito.verify method for mock object which is created by @Mockbean. It can check that how many times it calls, what argument specified, and so on. Please try it.

Solution 3:[3]

Here is one way to do it ( quite involved - it may be better to just wait for Mockito 4 where the default will be strict mocks, or wait until after the test finishes using the mock, and then use verifyNoMoreInteractins )

  1. Replace @MockBean with @Autowired with a test configuration with @Primary

  2. Create a default answer that throws an exception for any unstubbed function

Then override that answer with some stubbing - but you have to use doReturn instead of when thenReturn

// this is the component to mock
@Component
class ExtService {
    int f1(String a) {
        return 777;
    }
}
// this is the test class
@SpringBootTest
@RunWith(SpringRunner.class)
public class ApplicationTests {

    static class RuntimeExceptionAnswer implements Answer<Object> {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            throw new RuntimeException(
                    invocation.getMethod().getName() + " was not stubbed with the received arguments");
        }
    }

    @TestConfiguration
    public static class TestConfig {

        @Bean
        @Primary
        public ExtService mockExtService() {
            ExtService std = Mockito.mock(ExtService.class, new RuntimeExceptionAnswer());
            return std;
        }

    }

    // @MockBean ExtService extService;
    @Autowired
    ExtService extService; // replace mockBean

    @Test
    public void contextLoads() {

        Mockito.doReturn(1).when(extService).f1("abc"); // stubbing has to be in this format
        System.out.println(extService.f1("abc")); // returns 1
        System.out.println(extService.f1("abcd")); // throws exception
    }

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 hiroyukik
Solution 3