【Java】【Mockit】モックメソッドの引数と呼び出し回数の検証

2024年10月20日

本記事ではJUnitでのテストの中でMockitを使ってモック化したメソッドの呼び出し回数と呼び出し時に渡された引数の値を検証する方法を紹介します。

準備

検証環境

動作検証を行った環境は以下の通りです。

  • Java 21
  • Spring Boot 3.2.7

テスト対象

本記事では購入額と会員ランクから獲得ポイントを計算してDBに保存する処理をテスト対象とします。下図のようにPointServiceクラスをテスト対象とし、DBアクセスを行うPointRepositoryクラスをMockitoでモック化します。

PointServiceクラスとPointRepositoryクラスのソースコードは以下のように作成します。

PointServiceクラス

PointRepositoryクラスを使用しDBから顧客IDに紐づくポイント還元率を取得し、獲得ポイントを計算しDBへ保存します。

// パッケージ、インポートは省略

@RequiredArgsConstructor
@Service
public class PointService {

    private final PointRepository pointRepository;

    public BigDecimal calculateAndSavePoint(int customerId, BigDecimal purchaseAmount) {

        // 顧客IDからポイント還元率を取得
        var pointRate = pointRepository.getPointRate(customerId);

        // 獲得ポイントを計算
        var earnedPoint = purchaseAmount.multiply(pointRate);

        // 獲得ポイントを保存
        return pointRepository.savePoint(customerId, earnedPoint);
    }
}

PointRepositoryクラス

DBアクセスを行うリポジトリクラスのインターフェースです。

// パッケージ、インポートは省略

public interface PointRepository {

    BigDecimal getPointRate(int customerId);
    BigDecimal savePoint(int customerId, BigDecimal point);
}

PointRepositoryImplクラス

PointRepositoryの実装クラスです。未完成の状態を想定して各メソッドの処理は記述していません。

// パッケージ、インポートは省略

@Repository
public class PointRepositoryImpl implements PointRepository {
    @Override
    public BigDecimal getPointRate(int customerId) {
        return null;
    }

    @Override
    public BigDecimal savePoint(int customerId, BigDecimal point) {
        return null;
    }
}

テストコード

以下のようなテストコードを作成しました。このテストコードではPointRepositoryをモック化し、saveメソッドの実行回数と渡された引数を検証しています。

verifyメソッドを使用することでモック化したメソッドの呼び出し回数を検証することができます。実行回数はtimesメソッドを使って指定できます。

ArgumentCaptureクラスを使用することでモック化したメソッドに渡された引数の値を取得できます。値を検証したい引数ごとにArgumentCaptureクラスのインスタンスを作成します。

ArgumentCaptureクラスのインスタンスからgetValueメソッドを呼び出すことでメソッド実行時の引数の値を取得できます。取得した値をassertThatを使って検証しています。

// パッケージ、インポートは省略

@ExtendWith(MockitoExtension.class)
class PointServiceTest {

    @InjectMocks
    private PointService pointService;

    @Mock
    private PointRepository pointRepository;

    @Test
    public void test1() {

        // PointRepositoryクラスのgetPointRateメソッドは 0.01 を返すようにモック化する
        Mockito.when(pointRepository.getPointRate(Mockito.anyInt())).thenReturn(new BigDecimal("0.01"));

        // PointRepositoryクラスのsaveメソッドは 10.00 を返すようにモック化する
        Mockito.when(pointRepository.savePoint(Mockito.anyInt(), Mockito.any())).thenReturn(new BigDecimal("10.00"));

        // PointServiceクラスのテストを実施
        pointService.calculateAndSavePoint(10, new BigDecimal("1000"));

        // PointRepositoryクラスのsaveメソッド呼び出し回数を検証
        var customerIdCaptor = ArgumentCaptor.forClass(Integer.class);
        var earnedPointCapture= ArgumentCaptor.forClass(BigDecimal.class);
        verify(pointRepository, times(1)).savePoint(customerIdCaptor.capture(), earnedPointCapture.capture());

        // PointRepositoryクラスのsaveメソッドの呼び出し時の引数を検証
        var customerId = customerIdCaptor.getValue();
        var capturedPoint = earnedPointCapture.getValue();
        assertThat(customerId).isEqualTo(10);
        assertThat(capturedPoint).isEqualTo(new BigDecimal("10.00"));
    }

}

この記事ではSpring Bootで作成したプロジェクト内でMockitを使ってモック化する方法と、モック化したメソッドに対する引数、モック化したメソッドの呼び出し方法を検証する方法を紹介しました。

また、ソフトウェアテストの手法やテストの進め方については【この1冊でよくわかる】ソフトウェアテストの教科書で分かりやすく解説されています。