Difference between Spy and Mock thenCallRealMethod
Overview
In previous tutorial we saw difference between mock and spy with example. But partial mocking for which spy is used can also be done using mock thenCallRealMethod. So when should we use spy and when the mock thenCallRealMethod.Lets Begin
We will mock the EmployeePaymentService class defined in the previous tutorial.package com.javainuse.service; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; public class EmployeePaymentServiceTest_MockCallRealMethod { private int testWrkingDays = 25; private int testSalaryPerDay = 1000; private int testSalary = 25000; private String empId = "emp100"; //Mock class instance using mock @Mock private EmployeePaymentService employeePaymentService; /** * Setup before test. */ @BeforeMethod public void beforeMethod() { MockitoAnnotations.initMocks(this); } @Test public void testGetSalary() { //tell mockito to call actual methods instead of mocking when(employeePaymentService.getNoOfWorkingDays(anyString())).thenCallRealMethod(); when(employeePaymentService.getSalaryPerDay(anyString())).thenCallRealMethod(); //tell mockito to mock the following call when(employeePaymentService.processPay(anyString(), anyInt(), anyInt())).thenReturn(testSalary); //Actual call as defined above int returnedWrkingDays = employeePaymentService.getNoOfWorkingDays(empId); Assert.assertEquals(returnedWrkingDays, testWrkingDays); //Actual call as defined above int returnedSalaryPerDay = employeePaymentService.getSalaryPerDay(empId); Assert.assertEquals(returnedSalaryPerDay, testSalaryPerDay); //Mock call as defined above int returnedSalary = employeePaymentService.processPay(empId, testWrkingDays, testSalaryPerDay); Assert.assertEquals(returnedSalary, testSalary); } }
As we can see we called the actual implementation for getNoOfWorkingDays() and getSalaryPerDay() and mocked the processPay() method. So similar partial mocking achieved using spy is also achieved using Mock thenCallRealMethod(). Both can be used interchangeably. However there is major difference between the use of thenCallRealMethod and spy. When we use Mock the actual object instance is not created but bare-bones shell instance of the Class is created to track interactions. Whereas in case of spy we ourselves create the object instance to be used by spy. So using Mockito Spy guarantees that the real methods are called correctly.
For example-
public class EmployeePaymentService { EmployeePaymentService( final NamedParameterJdbcTemplate namedParameterJdbcTemplate) { this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; } public int getNoOfWorkingDays(String empId) { //call some query namedParameterJdbcTemplate.query(); } }If for a unit test case we mock the above EmployeePaymentService using Mock as-
@Mock private EmployeePaymentService employeePaymentService;
and later call the actual method getNoOfWorkingDays using thenCallRealMethod as follows-
when(employeePaymentService.getNoOfWorkingDays (anyString())).thenCallRealMethod();
int returnedWrkingDays = employeePaymentService.getNoOfWorkingDays(empId);
We get a java.lang.NullPointerException in the getNoOfWorkingDays method because the namedParameterJdbcTemplate has never been initialized. However if we were using the Mockito Spy this scenario would never arise because we would have ourselves created the EmployeePaymentService using constructor with namedJdbcTemplate.
Download Source Code
Download it - Java Mockito using thenCallRealMethodUnderstand Java 8 Method References using Simple Example Java - PermGen space vs MetaSpace Java 8 Lambda Expression- Hello World Example Java 8 Features Java Miscelleneous Topics Java Basic Topics Java- Main Menu