問題描述
有什么方法可以使用 Mockito 來模擬類中的某些方法,而不模擬其他方法?
Is there any way, using Mockito, to mock some methods in a class, but not others?
例如,在這個(誠然做作的)Stock
類中,我想模擬 getPrice()
和 getQuantity()
返回值(如下面的測試片段所示),但我希望 getValue()
執行在 Stock
類中編碼的乘法
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);
}
推薦答案
直接回答你的問題,是的,你可以模擬一些方法而不模擬其他方法.這稱為部分模擬.請參閱 關于部分模擬的 Mockito 文檔了解更多信息信息.
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
在這種情況下,每個方法實現都會被模擬,除非在 when(..)
子句中指定 thenCallRealMethod()
.
In that case, each method implementation is mocked, unless specify thenCallRealMethod()
in the when(..)
clause.
也有可能使用 spy 而不是 mock:
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
在這種情況下,所有方法實現都是真實的,除非您使用 when(..)
定義了模擬行為.
In that case, all method implementation are the real one, except if you have defined a mocked behaviour with when(..)
.
當您將 when(Object)
與上一個示例一樣與 spy 一起使用時,有一個重要的缺陷.真正的方法將被調用(因為 stock.getPrice()
在運行時在 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
<小時>
另一種可能是使用org.mockito.Mockito.CALLS_REAL_METHODS
,如:
Stock MOCK_STOCK = Mockito.mock( Stock.class, CALLS_REAL_METHODS );
這將未存根的調用委托給實際實現.
This delegates unstubbed calls to real implementations.
但是,對于您的示例,我相信它仍然會失敗,因為 getValue()
的實現依賴于 quantity
和 price
,而不是 getQuantity()
和 getPrice()
,這是你嘲笑的.
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);
}
這篇關于使用 Mockito 來模擬某些方法,但不能模擬其他方法的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!