java mockito教學 - 使用Mockito嘲笑一些方法,但不是其他方法




mockito教程 mockito中文 (5)

部分嘲笑類也支持通過間諜在mockito

List list = new LinkedList();
List spy = spy(list);

//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);

//using the spy calls real methods
spy.add("one");
spy.add("two");

//size() method was stubbed - 100 is printed
System.out.println(spy.size());

詳細解釋請查看1.10.192.7.22文檔。

有沒有什麼方法可以用Mockito來嘲笑課堂上的某些方法,而不是其他方法?

例如,在這個(可以承擔的)股票類中,我想模擬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);
}

要直接回答你的問題,是的,你可以嘲笑某些方法而不嘲笑其他人。 這被稱為部分模擬 。 有關部分模擬的更多信息,請參閱Mockito文檔

舉個例子,你可以在你的測試中做如下的事情:

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() ,否則每個方法實現都會被thenCallRealMethod()

另一種方式也可能是間諜而不是模擬

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(..)定義了一個模擬行為。

當你在前面的例子中使用間諜時,有一個重要的陷阱。 真正的方法將被調用(因為stock.getPrice()是在運行when(..)之前評估的)。 如果你的方法包含不應該被調用的邏輯,這可能是一個問題。 你可以這樣寫前面的例子:

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

然而,就你的例子而言,我相信它仍然會失敗,因為getValue()的實現依賴於quantityprice ,而不是getQuantity()getPrice() ,這是你嘲笑的。

它看起來像你想要的只是:

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

根據docs

Foo mock = mock(Foo.class, CALLS_REAL_METHODS);

// this calls the real implementation of Foo.getSomething()
value = mock.getSomething();

when(mock.getSomething()).thenReturn(fakeValue);

// now fakeValue is returned
value = mock.getSomething();

使用Mockito的間諜方法進行部分嘲弄可能是解決您的問題的方法,正如上面的答案中所述。 在某種程度上,我同意,對於具體的用例,嘲笑數據庫查找可能更合適。 根據我的經驗,這並不總是可行的 - 至少不是沒有其他解決方法 - 我認為這是非常麻煩或至少是脆弱的。 請注意,部分嘲諷不適用於盟友版本的Mockito。 您至少使用1.8.0。

我只是寫了一個簡單的原始問題的評論,而不是發布這個答案,但不允許這樣做。

還有一件事:我真的無法理解,在這裡問一個問題的次數很多時會在“你為什麼要這麼做”的問題上得到評論,而沒有至少試圖理解問題。 特別是當涉及到需要部分模擬的時候,真的有很多用例可以想像它會在哪裡有用。 這就是Mockito提供這種功能的原因。 這個功能當然不會被過度使用。 但是當我們談論測試用例設置,否則無法以非常複雜的方式建立時,應該使用間諜。


Java堆棧的確切功能未記錄,但它完全取決於分配給該線程的內存。

只需嘗試使用帶有stacksize的Thread構造函數,看看它是否變為常量。 我還沒試過,所以請分享結果。





java mocking mockito