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); } ```