2023.10.10
Spring Bootを用いてローカル環境でDBアクセスのインテグレーションテストを実装する
こんにちは、T.Iです。最近Spring Bootでテストを作成している際に、ローカル環境でDBアクセスのインテグレーションテストを実装したので、ご紹介します。
今回の環境としてはJava20、Spring Boot3.1.2を使用しました。
・依存パッケージ
ローカル環境でインテグレーションテストを実装するために以下のパッケージを追加します。
・spring-boot-starter-data-jpa
→今回はSpring Data JPAを使用することを前提にEntityを定義します。
・h2
→ローカルでDBアクセスのインテグレーションを行うため、こちらをDBとして使用します。
・mariadb-java-client
→DBアクセスするためのクライアントのパッケージ。今回はMariaDBを使用しますが、環境に合わせてください。
※Spring Bootの基本的なパッケージは追加されているものとします。
以下、gradle.buildの例です。
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' testImplementation 'com.h2database:h2:2.2.220'
・Entity
今回のようにローカル環境でDBアクセスのインテグレーションテストを行うためにはSpring Data JPAに従って以下のようにEntityの定義を行います。
import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; @Entity @Table(name = "tests") public class TestDAO { @Id @Column(name = "id") public Integer id; @Column(name = "name") public String name; }
今回テストを行う際は手動でschemaとtableは作成せず、Spring Data JPAに自動で作成してもらうのでEntityの定義の段階でテーブル、エンティティ、id、カラムの定義をしておく必要があります。
因みにですが、JpaRepositoryのinterfaceに命名規則に沿ってメソッドを追加することでDBへのアクセス処理を自動で実装してくれます。
import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; import jp.example.entities.TestDAO; //上で作成したEntity @Component public interface TestsJpaRepository extends JpaRepository<Test, Integer> { List<Test> findByNameIn(List<String> names); }
詳しい命名規則については公式ドキュメントを参照してください。
また、JoinやForeignKeyの実装、ネストしたオブジェクトの同時更新なども可能ですが、ここでは紹介しません。
・テスト
まずapplication.propertiesを編集して以下の設定項目を追加します。
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect // ここでDBのクライアントを指定する spring.datasource.url=jdbc:h2:mem:test;DATABASE_TO_UPPER=false;MODE=MYSQL;DB_CLOSE_ON_EXIT=FALSE // ここにH2接続設定を書く。 spring.batch.jdbc.initialize-schema=always // alwaysで起動時にtableを初期化する。neverだと起動しても初期化されない。
また、テストは実際のDBにアクセスしてテストを行うように実装を行います。
import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import jp.example.entities.TestDAO; //上で作成したEntity @DataJpaTest // ここを追加 @AutoConfigureTestDatabase(replace = Replace.NONE) // ここを追加 public class TestReportAdGroupSlotsDatabaseRepository { // 以下の二つはSpringBootApplicationTestが実行されるため、DIされる TestEntityManager entityManager; TestsJpaRepository repository; @Test public void readByReportAtAndSlotIdAndSspId() { TestDAO test = new TestDAO(); test.name = "name"; // ここでDBにデータをinsertする entityManager.persist(test); entityManager.flush(); TestDAO result = repository.findByNames(List.of("name")).stream().forEach((result)->assertEquals(result.name, test.name)); } }
これにより、テスト起動時にローカルでSpringBootApplicationとH2が起動し、H2にEntityに定義されたtableが自動で作成されます。その後、MariaDBクライアントを通してH2と通信することでインテグレーションテストを実現します。
今回の設定だとテスト終了後にH2のデータは消えるので注意してください。
さいごに
次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。インフラ設計、構築経験者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。 皆さんのご応募をお待ちしています。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD