きり丸アドベントカレンダー2020の9記事目です。
今回の記事でMyBatisのテストを行えるようにします。テスト用のスターターが準備されているので、テストのための準備は簡単です。ただし、テストのセットアップは慣れていないと、時間がかかってしまいます。
この記事を参考にサクっと環境構築していただけると幸いです。
H2とは
インメモリで展開できるDB。
メモリ内で展開できると並列実行できるので、総合的にかなり早くなります。実際に、PostgreSQLで実行すると並列実行できずに20分かかっていましたが、H2では4並列の5分でテストが終わるようになりました。
ただしデメリットとして、H2とPostgreSQLは結局DBとしては異なるので、細かい挙動が異なります。ですので、PostgreSQLで動作確認してからテストでH2に逆輸入すると、動かないことがあるのは痛いです。
基本的にテストは毎日何回も実行したいので、早く実行できることはメリットです。ただし、構文に引っかかったときにはH2とPostgreSQLのどちらでも動くようにする必要があるので、かなり苦労します。
ゴール
- MyBatisのテストを行う
- H2でテストを行う
- 設定ファイルの分割を行う
- アドベントカレンダー用のゴールでMyBatisのテストとは関係ありません
環境
- Java
- 15
- mybatis-spring-boot-starter
- 2.1.4
- mybatis-spring-boot-starter-test
- 2.1.3
- H2
手順
MyBatisのtestライブラリをインストールする
@MybatisTests
を使用したいので、mybatis-spring-boot-starter-test
の最新版2.1.3をテストコンパイル対象にします。@SpringBootTest
でもテストできますが、余計なimportしてしまったりするので、@MybatisTest
を使うようにしましょう。
ファイル名:build.gradle
dependencies {
testCompile "org.mybatis.spring.boot:mybatis-spring-boot-starter-test:2.1.3"
}
spring.profilesを使って設定ファイルを分割する
現在は、application.yml
にすべて記載してしまっています。この状態では、非常にテストがしづらい状態になってしまいます。ですので、DBの設定項目とそれ以外に分割しましょう。
spring.profiles.group
を使用すると、設定ファイルから設定ファイルを読み込めます。
ファイル名:application.yml
spring: profiles: active: - local group: local: - database-local - common
ファイル名:application-common.yml
spring: thymeleaf: mode: HTML mybatis: configuration: map-underscore-to-camel-case: true
ファイル名:application-database-local.yml
spring: datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://127.0.0.1:5432/postgres username: gitpod password:
DBのH2を使えるように設定ファイルを作成する
先にH2用の設定ファイルを用意します。特徴的な設定値としては、urlはインメモリでtestdbというデータベース名を指定しています。また、起動モードはPostgreSQLにしています。
また、DB_CLOSE_DELAY=-1
を指定すると、接続が切れるたびにデータベースがリセットされることを防ぎます。リセットされてしまうと、実行時間がかかるので、このやり方が良いでしょう。
ファイル名:application-database-h2.yml
spring: datasource: driver-class-name: org.h2.Driver url: jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1 username: root password: root
テスト時は、src/test/resources/application.yml
を読み込みます。testディレクトリ配下のapplication.ymlに次の設定を記載します。
ファイル名:application.yml
spring: profiles: active: - ut group: ut: - database-local - common2
このように設定することで、通常どおり起動した場合はDBの接続先がPotgreSQL、テストではDBの接続先がH2になります。
テストコードを書く
テストクラスに@MybatisTest
を指定します。テスト対象クラスをDIしたいので、@Autowired
をテスト対象クラスに付与します。この状態で、JUnit 5でのテストができる状態になりました。
あとは、データ追加のinsertメソッドとデータ取得のfindListメソッドはすでに用意していますので、データ準備にinsertメソッド、検証にfindListメソッドを呼ぶと目的どおりの項目がDBに登録されているかをテストできます。
なお、マスタデータ等のinsertメソッドのコードが無い場合、テストコード内でinsertメソッドを自作する必要があります。
ファイル名:TodoRepositoryTests.java
@MybatisTest // 設定ファイルを読み込んで、目的のクラスをDIできる状態にする public class TodoRepositoryTests { @Autowired // DIする TodoRepository todoRepository; @DisplayName("insertした結果をfindする") // テストの表示を変更する @Test // テスト対象のメソッドを表現する public void test_01() { // GIVEN 準備 TodoDto todoDto = TodoDto.builder().id(1).userId("kirimaru").action("豆腐買う").build(); todoRepository.insert(todoDto); // WHEN 実施 final List<TodoDto> kirimaru = todoRepository.findList("kirimaru"); // THEN 検証 assertThat(kirimaru).isEqualTo( List.of(todoDto) ); } }
ソースコード
このタイミングで、登録(Insert)と取得(Select)以外にも、更新(Update)と削除(Delete)も行うようにしています。
アドベントカレンダー9日目。
github.com
終わりに
「DBのテストのセットアップが大変だからやりたくありません!」というのは、今までの経験では受け入れられたことはありません。しかしUIのテストや他の構築が難しいテストに関してはセットアップが大変で、リターンが薄いから実施しないという判断は何度もしてきました。
「やれる」ことは分かっていても「できる」ように環境構築するには壁があります。
手元のSpringの入門書を読み直していますが、なぜかテスト関連の記載はないので、こういう記事で補完していただけると幸いです。
この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。
参考記事
H2:Featuresページ www.h2database.com
PlayFramework:H2データベース
(フレームワークは異なりますが、H2の設定値は参考になります)
www.playframework.com
類似記事
きり丸アドベントカレンダー2020 adventar.org
きり丸のHerokuページ
https://kirimaru-todoapp.herokuapp.com/
10日目のアドベントカレンダーの記事 https://nainaistar.hatenablog.com/entry/2020/12/10/083000nainaistar.hatenablog.com