有没有办法,使用Mockito来模拟一个类中的某些方法,而不是其他方法?
例如,在这个(公认的设计)Stock类中我想模拟getPrice()和getQuantity()返回值(如下面的测试片段所示),但我希望getValue()执行在Stock中编码的乘法类
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);
}
5 回答
要直接回答你的问题,是的,你可以模拟一些方法而不会嘲笑其他方法 . 这称为 partial mock . 有关更多信息,请参见the Mockito documentation on partial mocks .
对于您的示例,您可以在测试中执行以下操作:
在这种情况下,除非在
when(..)
子句中指定thenCallRealMethod()
,否则将模拟每个方法实现 .还有一种可能是 spy 而不是 mock 的另一种方式:
在这种情况下,除非您使用
when(..)
定义了模拟行为,否则所有方法实现都是真实的 .使用
when(Object)
与 Spy 一样,有一个重要的陷阱,如上例所示 . 将调用真实方法(因为在运行时when(..)
之前评估stock.getPrice()
) . 如果您的方法包含不应调用的逻辑,则可能会出现问题 . 您可以像这样编写上一个示例:但是,在你的例子中,我相信它仍然会失败,因为
getValue()
的实现依赖于quantity
和price
,而不是getQuantity()
和getPrice()
,这就是你所嘲笑的 .你真正想要的只是:
通过模拟中的 Spy 也支持对类进行部分模拟
有关详细说明,请查看1.10.19和2.7.22文档 .
根据docs:
根据问题,接受的答案是不正确的 .
对
Stock stock = mock(Stock.class);
的调用调用org.mockito.Mockito.mock(Class<T>)
,如下所示:值
RETURNS_DEFAULTS
的文档告诉:根据文档,你想要的是
org.mockito.Mockito.CALLS_REAL_METHODS
:因此,您的代码应如下所示:
使用Mockito的 Spy 方法进行部分 Mock 可以解决您的问题,如上面的答案中所述 . 在某种程度上,我同意,对于您的具体用例,模拟数据库查找可能更合适 . 根据我的经验,这并不总是可行的 - 至少在没有其他解决方法的情况下 - 我会认为这是非常麻烦或至少是脆弱的 . 请注意,部分模拟不适用于Mockito的盟友版本 . 你至少使用1.8.0 .
我本来只是为原始问题写了一个简单的评论,而不是发布这个答案,但StackOverflow不允许这样做 .
还有一件事:我真的无法理解,在这里被问到的问题多次被评论为“为什么你想这样做”而不至少试图理解问题 . 特别是当需要进行部分模拟时,我确实会想到很多用例 . 这就是Mockito的人提供这种功能的原因 . 这个功能当然不应该被滥用 . 但是当我们谈论测试用例设置时,否则无法以非常复杂的方式 Build ,应该使用 Spy .