【MyBatis】Spring BootでMyBatisマッパを単体テストする
この記事の概要
Spring Boot + MyBatis + PostgreSQLのプロジェクトでMyBatisマッパの単体テストを作成する方法を紹介します。
この記事の内容は以下の環境で動作確認しています。
- Spring Boot 3.4.7
- Java 21
- PostgreSQL 15.4
- myBatis-spring-boot-starter 3.0.5
- mybatis-spring-boot-starter-test 3.0.5
Spring BootプロジェクトでMyBatisを使用する際にはmybatis-spring-boot-starter, mybatis-spring-boot-starter-testを利用するとSpring Boot プロジェクト中のbuild.gradleへ依存関係を追加するだけで簡単に設定が完了します。
参考情報
テスト対象の処理概要
以下のようなカラムを持つBookテーブルからデータを検索する処理をMyBatisマッパーで作成します。MyBatisマッパーの単体テストを作ることが目的なので簡略したテーブル構成となっています。
| カラム名 | 型 | 概要 |
|---|---|---|
| id | INT | 主キーとなるID |
| name | VARCHAR(255) | 本の名称 |
| category_id | INT | 本が属するカテゴリーのID |
| updated_at | TIMESTAMP WITH TIME ZONE | データ更新日時 |
上記のBookテーブルのDDLを以下のように作成しました。
CREATE TABLE book (
id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
category_id INT NOT NULL,
published_at TIMESTAMP WITH TIME ZONE NOT NULL
);
MyBatisマッパーの実装
Bookテーブルから主キーで検索するだけのシンプルなマッパーを作成します。
@Mapper
public interface BookMapper {
Book findById(int bookId);
}
マッパーから実際に実行されるSQLは以下です。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.domain.mapper.BookMapper">
<select id="findById" resultType="com.example.demo.domain.model.Book">
SELECT
id,
book_title,
category_id,
updated_at
FROM book
WHERE id = #{bookId}
</select>
</mapper>
単体テストの構成
build.gradleに依存関係を追加します。
dependencies {
...
// MyBatis
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.5'
// PostgreSQL
runtimeOnly 'org.postgresql:postgresql'
// MyBatisマッパのテスト用
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.5'
}
単体テストは以下のように作成できます。MyBatis Generatorを使ったマッパの作成方法やMyBatisの設定については【MyBatis Generator 1.4.2】Spring Boot3でMyBatis Dynamic SQLを使用するをご参照ください。
package com.example;
// importは省略
@MybatisTest // ①
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // ②
@Sql("classpath:sql/BookMapper.sql") // ③
public class BookMapperTest {
// CustomerMapperをインジェクション
@Autowired
private BookMapper bookMapper;
@Test
public void test1() {
Book book = bookMapper.findById(1);
assertThat(book.id()).isEqualTo(1);
assertThat(book.name()).isEqualTo("test_book1");
assertThat(book.categoryId()).isEqualTo(1);
assertThat(book.updatedAt()).isEqualTo(OffsetDateTime.parse("2022-05-01T12:00:00+09:00"));
}
}
①がmybatis-spring-boot-starter-testで用意されているアノテーションです。MyBatisマッパの単体テストを作成するために使用します。mybatis-spring-boot-starter-test 2.0.1以降では@ExtendWith(SpringExtension.class)を省略可能です。@MybatisTestは@Transactionalを含んでいるので@Testを付与したテストごとにトランザクションが開始されます。
②が単体テストでPostgreSQLを使用するための設定です。デフォルトではインメモリDBを使用します。
③が単体テストで使用する初期データを投入するSQLです。必ずしも@SQLを使用する必要はありませんが、マッパのテストでマッパを使ってデータを投入するするのはテストの観点から避けました。BookMapperTest.sqlはresourcesディレクトリ内に以下のように作成しました。
INSERT INTO book
VALUES
(1, 'test_book1', 1, '2022-05-01T12:00:00+09'),
(2, 'test_book2', 2, '2022-05-02T12:00:00+09'),
(3, 'test_book3', 2, '2022-05-03T12:00:00+09');

