【H2】できるだけシンプルにJdbcTemplateを用いたテストが行えるようにする【SpringBoot】


やりたいこと

自作のRowMapperをテストするため、単一クラスで完結する範囲でDBの初期化 & データ挿入を行った上でJdbcTemplateを取得する必要が出ました。
当初はフレームワーク等を用いたりDIしたりする必要が有るかなと考えましたが、コンフィグを書くのが面倒なので、Java(Kotlin)内でべた書きする形で解決を模索しました。

やり方

最終的に以下の方針に落ち着きました。

  1. DBはH2のインメモリモードで、アプリケーションから起動する
  2. 1でDataSourceが取得できるので、この時点でJdbcTemplateを取得する
  3. テーブル作成/データ挿入などのDB操作はJdbcTemplate経由で行う

サンプルコード

import org.h2.jdbcx.JdbcDataSource
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource
import org.springframework.jdbc.core.simple.SimpleJdbcInsert
import javax.sql.DataSource

/* 略 */

// DBをインメモリモードで起動
val dataSource: DataSource = JdbcDataSource().apply {
    setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS APP\\;SET SCHEMA APP;")
}

// JdbcTempalte取得
val jdbcTemplate: JdbcTemplate = JdbcTemplate(dataSource)
// テーブル作成
jdbcTemplate.execute("""
    CREATE TABLE IF NOT EXISTS `foo_table` (
      `foo_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
      `foo_name` VARCHAR(255) NOT NULL,
      `foo_status` ENUM('active', 'archive', 'deleted') NOT NULL,
      `is_bar` ENUM('true', 'false') NOT NULL,
      `description` VARCHAR(1023) NULL DEFAULT NULL,
      PRIMARY KEY (`foo_id`)
    );
""".trimIndent())

// あらかじめ用意しておいたデータをinsert、ここではオブジェクトをSimpleJdbcInsertでinsertしている
val data = FooInsert(10, "Foo", FooStatus.archive, false, null)
SimpleJdbcInsert(jdbcTemplate).withTableName("foo_table").execute(BeanPropertySqlParameterSource(data))

おまけ: build.gradle

gradle.ktsですが、以下のように依存を設定しました。

build.gradle.kts
dependencies {
    /* 略 */

    // 使うのはRowMapperのみなため他はexclude、またバージョンそのものは使う相手に合わせるためcompileOnly
    compileOnly(group = "org.springframework", name = "spring-jdbc", version = "5.2.4.RELEASE") {
        exclude(module = "spring-beans")
        exclude(module = "spring-jcl")
        exclude(module = "spring-tx")
    }

    // テスト実行時には実体が無いと困るため、別口でimplementation
    testImplementation(group = "org.springframework", name = "spring-jdbc", version = "5.2.4.RELEASE")
    // https://mvnrepository.com/artifact/com.h2database/h2
    testImplementation(group = "com.h2database", name = "h2", version = "1.4.200")

    /* 略 */
}

参考にさせて頂いた記事