Is it possible, using Mockito, to create a partial mock where some methods are mocked but others retain their original behavior?
For instance, in the following Stock class, I want to mock the getPrice() and getQuantity() return values, but I want the getValue() method to execute the multiplication as defined in the Stock class:
public class Stock {
  private final double price;
  private final int quantity;
  Stock(double price, int quantity) {
    this.price = price;
    this.quantity = quantity;
  }
  public double getPrice() {
    return price;
  }
  public int getQuantity() {
    return quantity;
  }
  public double getValue() {
    return getPrice() * getQuantity();
  }
}
In the following test code, I attempt to mock the getPrice() and getQuantity() methods but find that getValue() does not perform the calculation as expected:
@Test
public void getValueTest() {
  Stock stock = mock(Stock.class);
  when(stock.getPrice()).thenReturn(100.00);
  when(stock.getQuantity()).thenReturn(200);
  double value = stock.getValue();
  // The assertion fails because the mock Stock getValue() method does not use the Stock.getValue() calculation code.
  assertEquals("Stock value not correct", 100.00 * 200, value, .00001);
}
             
            
              
              
              
            
           
          
            
            
              Use @Spy for Partial Mocks
You can use Mockito’s @Spy annotation to create a partial mock. This allows you to mock specific methods while keeping the original behavior of other methods.
Here’s how you can apply it:
import static org.mockito.Mockito.*;
public class StockTest {
  
  @Spy
  private Stock stock;
  @Test
  public void getValueTest() {
    // Mock the getPrice() and getQuantity() methods
    doReturn(100.00).when(stock).getPrice();
    doReturn(200).when(stock).getQuantity();
    
    double value = stock.getValue();
    // Assert the value using the real getValue() calculation
    assertEquals("Stock value not correct", 100.00 * 200, value, .00001);
  }
}
             
            
              
              
              
            
           
          
            
            
              Use a Custom Mock with Delegation
If you prefer to create a mock with specific behavior but without using @Spy, you can use Mockito’s Answer to delegate method calls to a real instance:
import static org.mockito.Mockito.*;
public class StockTest {
  @Test
  public void getValueTest() {
    // Create a real instance
    Stock realStock = new Stock(100.00, 200);
    
    // Create a mock and use an Answer to delegate method calls
    Stock mockStock = mock(Stock.class, new Answer<Object>() {
      @Override
      public Object answer(InvocationOnMock invocation) throws Throwable {
        // Delegate calls to the real instance
        return invocation.getMethod().invoke(realStock, invocation.getArguments());
      }
    });
    // Mock the getPrice() and getQuantity() methods
    when(mockStock.getPrice()).thenReturn(100.00);
    when(mockStock.getQuantity()).thenReturn(200);
    
    double value = mockStock.getValue();
    // Assert the value using the real getValue() calculation
    assertEquals("Stock value not correct", 100.00 * 200, value, .00001);
  }
}