最近はSpringで@Autowiredではなくコンストラクタインジェクションを使うようになった話

きっかけはこちらの記事。

pppurple.hatenablog.com

もちろん、コンストラクタインジェクションのことは知っていたのですがフィールドに@Autowiredのほうが記述が楽だしインジェクションされるのが明確なので基本的にはフィールドインジェクションを使っていました。
ただ、たまに困っていたのがユニットテストの時でMockito等でモック(Spy)したりインジェクションするクラスを切り替えるときがちょっと面倒。
テスト用のモッククラスは@PrimaryをつけてインジェクションしていたのですがテストクラスでフィールドインジェクションしたクラスをSpyするとメソッドの実行時にエラーが出たりしてフィールドインジェクションとテストは少し気をつけないとなーと思っていました。こちらは最終的に原因がわからず・・・。

そんなときに上記の記事を読んで、たしかにコンストラクタインジェクションもいいなーと思い始めて最近ではまずはコンストラクタインジェクションを使うようにしています。
LombokのサポートがあるとンストラクタもLombokのアノテーション任せにできるのでコードもスッキリします。

こんな感じのクラスがあったとします。

@Component
@RequiredArgsConstructor
public class FrogService {
  private final DogService dogService;
  private final CatService catService;
}

テストはこんな感じで書いています。

public class FrogTest {
  
  @Autowired
  DogService dogService;

  CatService catService;

  FrogService frogService;

  @Before
  public void setUp() {
    // catServiceをMockito
    catService = spy(new CatService());
    frogService = new frogService(dogService, catService);
  }

  // 以下テストコード
  @Test
  public void test() {
    // setup
    doNothing().when(catService).hoge()
  }

}

これでcatService#hogeは呼びされても何もしなくなります。その他にも特定の引数のときに特定のオブジェクトを返すとかもできます。 最初フィールドインジェクションからコンストラクタインジェクションに変えたときは記述が面倒だなーと思っていたのですがLombokのコンストラクタインジェクションを使っていると気にならなくなりました。