1. ホーム
  2. java

[解決済み] Mockitoを使用して、あるメソッドをモックし、他のメソッドをモックしない

2022-03-19 01:10:01

質問

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

解決方法は?

質問に直接答えるなら、はい、いくつかのメソッドをモックしても、他のメソッドをモックすることはできません。これは パーシャルモック . 参照 パーシャルモックに関する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

その場合、各メソッドの実装は、以下の指定がない限り、モック化されます。 thenCallRealMethod() の中にある when(..) 節を使用します。

また、逆に スパイ の代わりに モック :

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(..) .

を使用する場合、1つ重要な落とし穴があります。 when(Object) のように spy を使っています。本当のメソッドが呼び出されることになります(なぜなら 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


もう一つの可能性は org.mockito.Mockito.CALLS_REAL_METHODS のようなものである。

Stock MOCK_STOCK = Mockito.mock( Stock.class, CALLS_REAL_METHODS );

これは、非スタブ化された呼び出しを実際の実装に委ねるものです。


しかし、あなたの例では、まだ失敗すると思います。 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);
}