Part 5 – Mock vs Spy in Mockito

What have we learned so far

Part 1 – What is Mockito?
In this tutorial, we will understand below topics –
– What is a Mock Object?
– When should I mock?
– Mockito Framework
– Enable Mockito Annotations
– How to Mock Object with @Mock & @InjectMock annotations in Spring application?
https://www.onlyfullstack.com/what-is-mock-object-what-is-mockito/

Part 2 – How to mock methods with Mockito?
 – How to mock methods?
1. when/then
2. when/thenThrow
3. when/thenAnswer
https://www.onlyfullstack.com/how-to-mock-methods-with-mockito/
Part 3- How to mock void methods with Mockito
 – Mocking Void Methods
– Three ways to mock the void method:
1. doNothing/when
2. doAnswer/when
3. doThrow/when
https://www.onlyfullstack.com/how-to-mock-void-methods-with-mockito/
Part 4 – How to verify mocks in Mockito
– Simple verify method
– Variations in verify method
– Verify with the number of times
– Mockito Verify Order of Invocation
https://www.onlyfullstack.com/how-to-verify-the-mocks-in-mockito/



Mockito Mock vs Spy

Let’s see the differences in Mock and Spy


1. Object declaration –
Mock – We don’t need to instantiate the mock List as the @Mock will create and instantiate the list for us.

Spy- We need to instantiate the list object as the @Spy will use the real object’s method if we don’t mock them.

/*
 We dont need to instantiate the mock List as the @Mock will create and instantiate the list for us
 */
@Mock
private List<String> mockedList;

/*
We need to instantiate the list object as the @Spy will use the real objects method if we dont mock them
 */
@Spy
private List<String> spyList = new ArrayList();

2. When the methods are not mocked –
Mock – If we don’t mock the methods of @Mock object and try to call them then it will not do anything.

Spy – add method is not mocked so the spyList will execute the default behaviour of the add method and it will add a new String into the list.

@RunWith(MockitoJUnitRunner.class)
public final class MockVsSpy {

    /*
     We dont need to instantiate the mock List as the @Mock will create and instantiate the list for us
     */
    @Mock
    private List<String> mockedList;

    /*
    We need to instantiate the list object as the @Spy will use the real objects method if we dont mock them
     */
    @Spy
    private List<String> spyList = new ArrayList();

    @Test
    public void testMockList_checkDefaultBehaviour_whenMethodIsNotMocked() {
        /*If we dont mock the methods of @Mock object and try to call them
        then it will not do anything.*/

        mockedList.add("test"); // add the String into list which will not do anything
        assertNull(mockedList.get(0)); // As the String was not added into the list it will return null value
    }

    @Test
    public void testSpyList_checkDefaultBehaviour_whenMethodIsNotMocked() {
        /* add method is not mocked so the spyList will execute
        * the default behaviour of the add method and it will add a new String into list*/
        spyList.add("test");
        assertEquals("test", spyList.get(0));
    }
}

3. When the method is mocked –
Mock – Mock will execute as per the above example and it will not add or get the element from the mockedList.

Spy – add method is not mocked so the spyList will execute the default behaviour of the add method and it will add a new String into the list.

@Test
public void testMockList_whenMethodIsMocked() {
    /*If we dont mock the methods of @Mock object and try to call them
    then it will not do anything.*/
    when(mockedList.size()).thenReturn(10);
    mockedList.add("One");
    assertNull(mockedList.get(0)); // Again the execution of add and get methods will not have any impact on mocked object

    assertEquals(10, mockedList.size()); // As the String was not added into the list it will return null value
}

@Test
public void testSpyList_whenMethodIsMocked() {
    /* add method is not mocked so the spyList will execute
     * the default behaviour of the add method and it will add a new String into list*/
    when(spyList.size()).thenReturn(10);
    spyList.add("One");
    assertEquals("One", spyList.get(0));

    assertEquals(10, spyList.size()); // size method will return 10 as we have mocked its implementation
}

Source Code
Download the source code of JUnit tutorial from below git repository :
unit-testing-and-integration-testing-with-spring-boot

Mockito Tutorial
https://www.onlyfullstack.com/mockito-tutorial/