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);
}
Best Answer
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:
In that case, each method implementation is mocked, unless specify
thenCallRealMethod()
in thewhen(..)
clause.There is also a possibility the other way around with spy instead of mock:
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 (becausestock.getPrice()
is evaluated beforewhen(..)
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:Another possibility may be to use
org.mockito.Mockito.CALLS_REAL_METHODS
, such as:This delegates unstubbed calls to real implementations.
However, with your example, I believe it will still fail, since the implementation of
getValue()
relies onquantity
andprice
, rather thangetQuantity()
andgetPrice()
, which is what you've mocked.Another possibility is to avoid mocks altogether: