ユニットテストにおけるモックとスタブの違いと使用方法


モックとは、テスト対象のコンポーネントと依存関係にある外部コンポーネントやリソースをシミュレートするものです。モックは、特定のメソッドが呼び出されたかどうかや、呼び出された際の引数や戻り値を検証するために使用されます。モックは、外部の依存関係を制御することで、テストの安定性や独立性を高めることができます。

一方、スタブは、テスト対象のコンポーネントが依存しているコンポーネントやリソースの代替品です。スタブは、テスト対象のコンポーネントとのインタラクションをシンプルにするために使用され、特定のメソッドの定義済みの結果を返すことができます。スタブは、外部の依存関係にアクセスする必要がないため、テストの速度を向上させることができます。

モックとスタブの使用法について具体的なコード例を見てみましょう。

例えば、以下のようなクラスがあるとします。

class UserManager {
  private EmailService emailService;
  public UserManager(EmailService emailService) {
    this.emailService = emailService;
  }
  public void registerUser(User user) {
    // ユーザーの登録処理
    emailService.sendEmail(user.getEmail(), "Welcome!");
  }
}

このクラスをテストする際に、EmailServiceの依存関係をモックかスタブで置き換えることができます。

モックを使用する場合、EmailServiceの代わりにモックオブジェクトを注入します。モックオブジェクトは、sendEmailメソッドが呼び出されたかどうかや、引数が正しいかどうかを検証することができます。

@Test
public void testRegisterUserWithMock() {
  EmailService mockEmailService = mock(EmailService.class);
  UserManager userManager = new UserManager(mockEmailService);
  User user = new User("John", "[email protected]");
  userManager.registerUser(user);
  // メソッドが1回呼び出されたかどうかを検証
  verify(mockEmailService, times(1)).sendEmail(eq("[email protected]"), eq("Welcome!"));
}

スタブを使用する場合、EmailServiceの代わりにスタブオブジェクトを注入します。スタブオブジェクトは、予め定義された結果を返すことができます。


@Test
public void testRegisterUserWithStub() {
  EmailService stubEmailService = new StubEmailService();
  UserManager userManager = new UserManager(stubEmailService);

  User user = new User("John", "[email protected]");
  userManager.registerUser(user);

  // メソッドの結果を検証
  // StubEmailServiceは常にtrueを返すため、メールが送信されたことを確認できる
  assertTrue("メールが送信されました", stubEmailService.isEmailSent());
}

モックとスタブの違いを理解し、適切に使用することで、ユニットテストの効果と品質を向上させることができます。モックは外部の依存関係の振る舞いを検証し、スタブはテスト対象のコンポーネントとのインタラクションを簡素化します。適切な場面で適切な方法を使用することを心がけましょう。

このブログ投稿は、ユニットテストにおけるモックとスタブの違いと使用方法について説明しています。