Help us understand the problem. What is going on with this article?

JUnit の ExternalResource クラスを継承したクラスの中で Spring Boot の Java Configuration のクラスで定義した DataSource Bean をインジェクションする

More than 5 years have passed since last update.

複数のテストクラスの共通の前処理、後処理を作成したい場合、JUnit の ExternalResource クラスを継承したクラスを用意すれば実現できますが、ExternalResource クラスを継承したクラスの中で Spring Boot の Java Configuration のクラスで定義した DataSource Bean をインジェクションして使いたいと思い、調査に結構時間がかかったのでそのメモ書きです。

例えば Spring Boot の Webアプリケーションの中で以下のように Java Configuration のクラスで DataSource Bean を定義しているものとします。

@Configuration
public class ApplicationConfig {

    @Bean
    @ConfigurationProperties("spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

}

テストクラスの共通処理として ExternalResource クラスを継承したクラスを作成し、その中で以下のように DataSource を @Autowired アノテーションを付加して定義した後、テストクラスの方では TestDataResource を @Rule アノテーションを付加して定義したのですが、テストを実行すると TestDataResource クラスの before メソッド内の dataSource を利用しているところで NullPointerException が出てテストが実行できませんでした。

※TestDataResource クラスの before, after メソッド内で実現しようとしていたのは、DbUnit を利用して既存データのバックアップ取得&テストデータへの入替、バックアップからのリストアの処理です。

public class TestDataResource extends ExternalResource {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void before() throws Throwable {
        IDatabaseConnection conn = new DatabaseConnection(dataSource.getConnection());
        .....
    }

}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class SampleControllerTest {

    @Rule
    public TestDataResource testDataResource = new TestDataResource();

    @Test
    .....

}

この後調べて修正したのは以下の2点です。

  • そもそもクラス内で @Autowired をフィールドに付加するのにクラスに何もアノテーションを付加していなかったので、@Component アノテーションを付加しました。
  • ExternalResource を使う時のサンプルコードとして public TestDataResource testDataResource = new TestDataResource(); の形式でテストクラスに定義するよう書かれている場合が多かったのですが、= new TestDataResource() でインスタンスを生成するのではなく @Autowired アノテーションを付加して Spring のDIコンテナにインスタンスを生成してインジェクションしてもらうようにしました。

修正後のソースは以下のようになります。これで TestDataResource クラスの before, after メソッド内で dataSource を利用できるようになりました。

@Component
public class TestDataResource extends ExternalResource {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void before() throws Throwable {
        IDatabaseConnection conn = new DatabaseConnection(dataSource.getConnection());
        .....
    }

}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class SampleControllerTest {

    @Rule
    @Autowired
    public TestDataResource testDataResource;

    @Test
    .....

}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away