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);
}
The accepted answer is not correct according to the question.
The call to
Stock stock = mock(Stock.class);
callsorg.mockito.Mockito.mock(Class<T>)
which looks like this:The docs of the value
RETURNS_DEFAULTS
tell:What you want is
org.mockito.Mockito.CALLS_REAL_METHODS
according to the docs:Thus your code should look like:
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 arround 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: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.What it really seems like you want is just:
According to docs :
Partial mocking using Mockito's spy method could be the solution to your problem, as already stated in the answers above. To some degree I agree that, for your concrete use case, it may be more appropriate to mock the DB lookup. From my experience this is not always possible - at least not without other workarounds - that I would consider as being very cumbersome or at least fragile. Note, that partial mocking does not work with ally versions of Mockito. You have use at least 1.8.0.
I would have just written a simple comment for the original question instead of posting this answer, but StackOverflow does not allow this.
Just one more thing: I really cannot understand that many times a question is being asked here gets comment with "Why you want to do this" without at least trying to understand the problem. Escpecially when it comes to then need for partial mocking there are really a lot of use cases that I could imagine where it would be useful. That's why the guys from Mockito provided that functionality. This feature should of course not be overused. But when we talk about test case setups that otherwise could not be established in a very complicated way, spying should be used.
Partial mocking of a class is also supported via Spy in mockito
Check the
1.10.19
and2.7.22
docs for detailed explanation.