Use Mockito to mock some methods but not others

java, mocking, mockito

Solution

To directly answer your question, yes, you can mock some methods without mocking others. This is called a partial mock. See the Mockito documentation on partial mocks for more information.

For your example, you can do something like the following, in your test:

Stock stock = mock(Stock.class);
when(stock.getPrice()).thenReturn(100.00);    // Mock implementation
when(stock.getQuantity()).thenReturn(200);    // Mock implementation
when(stock.getValue()).thenCallRealMethod();  // Real implementation

In that case, each method implementation is mocked, unless specify `thenCallRealMethod()` in the `when(..)` clause.

There is also a possibility the other way around with spy instead of mock:

Stock stock = spy(Stock.class);
when(stock.getPrice()).thenReturn(100.00);    // Mock implementation
when(stock.getQuantity()).thenReturn(200);    // Mock implementation
// All other method call will use the real implementations

In that case, all method implementation are the real one, except if you have defined a mocked behaviour with `when(..)`.

There is one important pitfall when you use `when(Object)` with spy like in the previous example. The real method will be called (because `stock.getPrice()` is evaluated before `when(..)` at runtime). This can be a problem if your method contains logic that should not be called. You can write the previous example like this:

Stock stock = spy(Stock.class);
doReturn(100.00).when(stock).getPrice();    // Mock implementation
doReturn(200).when(stock).getQuantity();    // Mock implementation
// All other method call will use the real implementations

Another possibility may be to use `org.mockito.Mockito.CALLS_REAL_METHODS`, such as:

Stock MOCK_STOCK = Mockito.mock( Stock.class, CALLS_REAL_METHODS );

This delegates unstubbed calls to real implementations.

However, with your example, I believe it will still fail, since the implementation of `getValue()` relies on `quantity` and `price`, rather than `getQuantity()` and `getPrice()`, which is what you've mocked.

Another possibility is to avoid mocks altogether:

@Test
public void getValueTest() {
    Stock stock = new Stock(100.00, 200);
    double value = stock.getValue();
    assertEquals("Stock value not correct", 100.00*200, value, .00001);
}

Problem

Is there any way, using Mockito, to mock some methods in a class, but not others? For example, in this (admittedly contrived) `Stock` class I want to mock the `getPrice()` and `getQuantity()` return values (as shown in the test snippet below) but I want the `getValue()` to perform the multiplication as coded 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(); } @Test public void getValueTest() { Stock stock = mock(Stock.class); when(stock.getPrice()).thenReturn(100.00); when(stock.getQuantity()).thenReturn(200); double value = stock.getValue(); // Unfortunately the following assert fails, because the mock Stock getValue() method does not perform the Stock.getValue() calculation code. assertEquals("Stock value not correct", 100.00*200, value, .00001); } ```

Original source