Java 逆引き集 | 依存注入(コンストラクタ注入の利点) — テスト容易性

Java Java
スポンサーリンク

依存注入(コンストラクタ注入の利点) — テスト容易性

Javaでよく使われる設計パターンの一つが 依存注入(Dependency Injection, DI)
その中でも「コンストラクタ注入」は、テストがしやすくなるという大きな利点があります。初心者向けに、コード例を交えて解説します。


依存注入とは?

  • 依存関係: クラスが他のクラスを使うこと。
  • 依存注入: 依存するオブジェクトを「自分で作る」のではなく「外から渡してもらう」こと。
  • 目的: 柔軟性・再利用性・テスト容易性を高める。

コンストラクタ注入の基本形

class Service {
    public void execute() {
        System.out.println("サービス実行");
    }
}

class Controller {
    private final Service service;

    // コンストラクタで依存を注入
    public Controller(Service service) {
        this.service = service;
    }

    public void run() {
        service.execute();
    }
}
Java

👉 Controller は Service を「自分で new」しない。外部から渡してもらう。


利点(特にテスト容易性)

  1. 依存を差し替えられる
    • 本番用の Service と、テスト用のダミー Service を切り替え可能。
  2. モックを使ったテストが簡単
    • JUnit や Mockito でモックを渡せる。
  3. クラスの責務が明確
    • Controller は「Service を使う」だけで「Service を作る」責務を持たない。

例題で練習

例題1: テスト用のダミー依存を注入

class DummyService extends Service {
    @Override
    public void execute() {
        System.out.println("テスト用サービス実行");
    }
}

public class TestController {
    public static void main(String[] args) {
        Service dummy = new DummyService();
        Controller controller = new Controller(dummy);
        controller.run(); // テスト用サービス実行
    }
}
Java

👉 本番コードを変えずにテスト用の依存を注入できる。


例題2: Mockitoでモック注入

import static org.mockito.Mockito.*;

public class ControllerTest {
    @org.junit.jupiter.api.Test
    void testRun() {
        Service mockService = mock(Service.class);

        Controller controller = new Controller(mockService);
        controller.run();

        verify(mockService).execute(); // 呼び出し確認
    }
}
Java

👉 モックを渡すことで、Controller の動作だけをテストできる。


テンプレート集

コンストラクタ注入

class ClassA {
    private final Dependency dep;

    public ClassA(Dependency dep) {
        this.dep = dep;
    }
}
Java

テスト用依存の差し替え

Dependency testDep = new TestDependency();
ClassA obj = new ClassA(testDep);
Java

モック注入(Mockito)

Dependency mockDep = mock(Dependency.class);
ClassA obj = new ClassA(mockDep);
Java

実務のコツと落とし穴

  • フィールドに直接 new しない: テスト不能になる。
  • final フィールドにする: 不変性が保たれ、設計が明確。
  • 依存が多すぎる場合: 設計を見直す。責務分割が必要。
  • DIフレームワーク: Spring などでは自動で依存を注入してくれるが、基本は同じ。

まとめ

  • コンストラクタ注入は依存を外部から渡す仕組み。
  • テスト容易性: ダミーやモックを渡せるので単体テストが簡単。
  • 責務分離: クラスは「依存を使う」だけに集中できる。

👉 練習課題として「メール送信クラス」を作り、テスト時には「ダミー送信クラス」を注入して動作確認すると、コンストラクタ注入の利点が体感できます。

タイトルとURLをコピーしました