依存注入(コンストラクタ注入の利点) — テスト容易性
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」しない。外部から渡してもらう。
利点(特にテスト容易性)
- 依存を差し替えられる
- 本番用の Service と、テスト用のダミー Service を切り替え可能。
- モックを使ったテストが簡単
- JUnit や Mockito でモックを渡せる。
- クラスの責務が明確
- 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 などでは自動で依存を注入してくれるが、基本は同じ。
まとめ
- コンストラクタ注入は依存を外部から渡す仕組み。
- テスト容易性: ダミーやモックを渡せるので単体テストが簡単。
- 責務分離: クラスは「依存を使う」だけに集中できる。
👉 練習課題として「メール送信クラス」を作り、テスト時には「ダミー送信クラス」を注入して動作確認すると、コンストラクタ注入の利点が体感できます。
