logo
Interview
Mocking Interview Questions
Are you an expert in disguise?
mocking
Question 1
What is the difference between Mockito's Mock and Spy notion?
Mock
Mock object replaces the mocked class completely, returning recorded or default values.
That's why you can create a mock just out of an interface or an abstract class. There is no concrete class needed.


Spy
You create spies by wrapping a real object. When you use the spy then the real methods are called by default. All the methods that needs to be stubbed, need to be configured explicitly.
Spies should be used carefully and occasionally. This relates mostly to legacy code.
Option 1

  @BeforeEach
  public void init(){
    MockitoAnnotations.initMocks(this);
  }


Option 2

  @ExtendWith(MockitoExtension.class)
  public class SystemTest(){

The most important benefits would be:
  • Ability to omit calling real implementation of dependent objects.
  • Stubbing the response of dependent objects based on certain needs of our tests.
  • Possibility to verify that certain methods of a mock were called.


Unit test has to always be run in an isolation from other components, unless they contain trivial logic.
Most of the time the SUT has a bunch of dependencies and they are far from being trivial.
This is where the mocking framework comes in. We can easily stub unnecessary behaviour and just verify that a certain call happened with certain input.
Dummy
The only aim for it is to be passed as a parameter and meet the type constraint for a certain method.
Dummies are not stubbed nor is their behaviour verified.


Stub
A stub is type of an object that has configured one or many of its methods to return a certain value based on certain input parameters.
Ideally we do not verify behaviour on a stub, its meant for supplying expected values to the SUT.


Mock
We create a mock in order to verify that its certain behaviour has been triggered.
We usually have commands in mind (void method). Ideally we do not stub a mock.
In general if there is a plethora of mocking and stubbing present in your test class that is a bad sign.
Most likely the OO design needs to be refactored in order to create more smaller classes following the Single Responsibility Principle.

Besides that:
  • Mocking a POJO object or any other trivial object that does not contain any special logic.
  • Stubbing a utility method. Most of them are not complex and do not contain further dependencies.
  • Stubbing a private method. These are implementation detail. We leave them as they are.
We never stub private methods. They are an implementation detail of the SUT.

Think of them as extensions of the public methods. These are the ones that dictate the behaviour and they are the ones available to the clients.

They change a lot faster than the public methods and would require a lot more maintenance (even if the actual public behaviour does not change).

The only time that it is justified to mock private members is during the testing of a legacy code where refactoring is not an option a lot of the time.
We verify in order to make sure that a certain actions have been triggered on dependencies of a SUT. A lot of the time the dependencies are to complex to invoke their implementation and we are forced to mock/stub. Frankly we should not even care, and a simple check of an interface invocation with certain parameters is more than enough.
The more mocks we need to use in our unit tests, the more questionable the quality.

We cannot escape mocking altogether as even the smallest classes usually are dependent on some other resource. But if we need to use a couple of mocks and a dozen of stubbing statements before we can invoke the SUT and make our tests pass, then something is wrong.

Most likely we need to decouple our code into more specialized classes. This will help us follow the Single Responsibility Principle and make it easier to test particular feature.
With non-void methods we always have an option to choose between the

when().then()

and the

doXX().when()

When we stub void methods, most of the time in order for them to throw a certain exception we always have to start with the doXX() option:

  doThrow(new ThereIsAProblemException()).when(mySut).myVoidMethod();

The most important ones would be:
  • Ability to invoke and expect same results on different sets of input arguments.
  • Sometimes we do not care about the actual values. We just care that they meet the type constraint.
  • We can create our own custom matchers that might contain more complex validations if needed.