この記事の対象
Spring 2.2.x
spring-test 5.2
JUnit 5.6
なにがしたかったの?
テスト実行をする際に、@SpringBootApplicationによるrunが実行されてしまうことを回避したかったのですが、そうすると、テストコード側でApplicationContextを利用できなくてハマってしまいました。
解決できたので、備忘録として…
なにゆえにハマったのか?
下記のようなテストコードを書いていました。
@SpringJUnitConfig(classes = {ComponentA.class})
@EnableConfigurationProperties(value = {PrimaryConfiguration.class, SecondaryConfiguration.class})
@ExtendWith(SpringExtension.class)
public class ComponentATest {
@Autowired
public ApplicationContext ctx;
@Test
public final void testA {
ComponentA testObj = new ComponentA();
ctx.getAutowireCapableBeanFactory().autowireBean(testObj);
// テスト対象メソッドの実行
testObj.exec()
}
上記のテストのようにテスト対象のクラス内にAutowiredしているオブジェクトが存在するため、AutowireCapableBeanFactoryを利用して、インスタンスにDIを注入しようとしたのですが、ApplicationContextがDIされず、nullが返却されるため、テストが出来ないという状態でした。
先の通り、@SpringJUnitConfigを利用せずに、@SpringBootTestを利用すれば良いのですが、諸事情により、本体アプリが実行されてしまうと不都合があるため、@SpringBootTestを使用せずにテストを実行したかったのです。
解決方法
@SpringJUnitConfigアノテーションにinitializersを付与するだけでOKです。
@SpringJUnitConfig(classes = {ComponentA.class},
initializers = ConfigFileApplicationContextInitializer.class)
ただし、initializersによりテストメソッド実行の度にApplicationContextを再生成するので、テストケースが大量にある場合は、素直にDIオブジェクトをMock/Spyした方が良いと思います。
これだけのために半日を無駄にした私のような犠牲者を出さないために…お役たてば幸いです。