ユニットテストのモックとスタブ

Javaによるテスト入門

Maria Milusheva

Senior Software Engineer

動機: 依存関係

前回の依存関係フローを思い出してください: 通貨換算アプリは銀行サーバーに依存します。 銀行デモの依存関係フローの Mermaid グラフ

為替レートは本質的に予測不能なため、計算の検証が不可能です。

Javaによるテスト入門

テストにおける依存関係管理

モック: テストで使いにくい実オブジェクトの代わりに、外部依存に頼らず検証できるよう模擬のオブジェクト/振る舞いを作ること。


import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

モックの例

Javaによるテスト入門

モック化

  • モック = テスト上だけ本物のように振る舞う代役

前回のコードを考えます:

public double convertEuroTo(String currency, double amount) {
    double rate = this.bank.getRateEuroTo(currency);
    return amount * rate;
}

➡ テスト用に EuropeanCentralBankServer を予測可能にする

Javaによるテスト入門

モック化: 通貨換算

モックを使ったテスト例:

@Test
void convert_returnsExpectedValue() {
    EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
    ExchangeApp exchangeApp = new ExchangeApp(bank);

// モックに動作を定義 when(bank.getRateEuroTo("USD")).thenReturn(1.1);
// モックの getRateEuroTo を呼び、事前設定の値を取得 double result = exchangeApp.convertEuroTo("USD", 1000); assertEquals(1100, result); // 正確な戻り値でアサート可能 }
Javaによるテスト入門

よくあるミス

モックの設定を忘れないでください:

@Test
void convert_returnsExpectedValue() {
    EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
    ExchangeApp exchangeApp = new ExchangeApp(bank);

    // 設定なし - モックは getRateEuroTo への応答方法を知らない
    double result = exchangeApp.convertEuroTo("USD", 1000);

    assertEquals(1100, result); // モック未設定のため失敗
}
Javaによるテスト入門

スタブ化

テスト失敗:

org.opentest4j.AssertionFailedError: 
Expected :1100.0
Actual   :0.0

モックに振る舞いを与えることを「スタブ化」と呼びます。

スタブ化: テスト中の呼び出しに最小限の事前定義の応答を返し、それ以外には基本的に反応しないこと。

Javaによるテスト入門

Mockito での例外

Mockito はエラーシナリオも再現できます:

EuropeanCentralBankServer bank = mock(EuropeanCentralBankServer.class);
ExchangeApp exchangeApp = new ExchangeApp(bank);
// thenReturn() の代わりに thenThrow() を使用
when(bank.getRateEuroTo("USD"))
        .thenThrow(new RuntimeException("Bank server unavailable."));

exchangeApp.convertEuroTo("USD", 1000); // getRateEuroTo が例外を投げる
Javaによるテスト入門

Let's practice!

Javaによるテスト入門

Preparing Video For Download...