最近はSpringで@Autowiredではなくコンストラクタインジェクションを使うようになった話
きっかけはこちらの記事。
もちろん、コンストラクタインジェクションのことは知っていたのですがフィールドに@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
のコンストラクタインジェクションを使っていると気にならなくなりました。