truncate table文によって、テーブルの全データを削除することができるが、truncate table文を実行した後でロールバックできるかどうかは、DBの種類によって異なる。
今回は、JUnit5 DBUnitを利用して、truncate table文を実行した時の動きを確認してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
やってみたこと
- 作成したサンプルプログラムの構成
- Oracleの場合のソースコードとテスト実行結果
- MySQLの場合のソースコードとテスト実行結果
- PostgreSQLの場合のソースコードとテスト実行結果
- SQL Serverの場合のソースコードとテスト実行結果
作成したサンプルプログラムの構成
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、このブログで掲載するソースコードを示す。
test.propertiesの内容は以下の通りで、JUnit5 DBUnitで利用する各DBの接続先を示していて、各DBの接続定義となるDemoTest~Configクラスで参照している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # DB接続先(Oracle) spring.datasourceut-ora.url=jdbc:oracle:thin:@localhost:1521:xe spring.datasourceut-ora.username=USER01 spring.datasourceut-ora.password=USER01 spring.datasourceut-ora.driverClassName=oracle.jdbc.driver.OracleDriver # DB接続先(MySQL) spring.datasourceut-ms.url=jdbc:mysql://localhost:3306/user01?serverTimezone=JST spring.datasourceut-ms.username=USER01 spring.datasourceut-ms.password=USER01 spring.datasourceut-ms.driverClassName=com.mysql.cj.jdbc.Driver # DB接続情報(PostgreSQL) spring.datasourceut-ps.url=jdbc:postgresql://localhost:5432/USER01 spring.datasourceut-ps.username=USER01 spring.datasourceut-ps.password=USER01 spring.datasourceut-ps.driverClassName=org.postgresql.Driver # DB接続先(SQLServer) spring.datasourceut-ss.url=jdbc:sqlserver://localhost:1433;databaseName=master spring.datasourceut-ss.username=USER01 spring.datasourceut-ss.password=USER01 spring.datasourceut-ss.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver |
また、上記赤枠以外のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/junit5-dbunit-truncate-table/demo
Oracleの場合のソースコードとテスト実行結果
テスト対象となるMapperの内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.example.demo.mapper.ora; import com.example.demo.mapper.UserData; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserDataMapperOra { /** * Oracleでユーザーデータテーブル(user_data)の全データを取得する * @return ユーザーデータテーブル(user_data)の全データ */ List<UserData> findAll(); /** * Oracleでユーザーデータテーブル(user_data)の全データを削除する */ void truncateUserData(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?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.mapper.ora.UserDataMapperOra"> <resultMap id="userDataResultMap" type="com.example.demo.mapper.UserData" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="birthY" property="birthY" jdbcType="VARCHAR" /> <result column="birthM" property="birthM" jdbcType="VARCHAR" /> <result column="birthD" property="birthD" jdbcType="VARCHAR" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="memo" property="memo" jdbcType="VARCHAR" /> <result column="sex_value" property="sex_value" jdbcType="VARCHAR" /> </resultMap> <select id="findAll" resultMap="userDataResultMap"> SELECT id , name , birth_year as birthY , birth_month as birthM , birth_day as birthD , sex , memo , CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '' END AS sex_value FROM USER_DATA </select> <update id="truncateUserData"> TRUNCATE TABLE USER_DATA </update> </mapper> |
また、JUnit5 DBUnitで利用するDB接続先設定の内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | package com.example.demo.mapper.ora; import com.github.springtestdbunit.bean.DatabaseConfigBean; import com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean; import org.dbunit.ext.oracle.Oracle10DataTypeFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; // MyBatisのテストを実行する際のDB接続定義 // @MybatisTestアノテーションでテストを実行する際、 // Spring Bootアプリケーションが起動するようにする。 // その際、com.example.demo.mapper.oraフォルダ下のインスタンス // (UserDataMapper)のみがDIで使用できるようになる。 @SpringBootApplication @PropertySource(value = {"classpath:test.properties"}) public class DemoTestOraConfig { /** * Oracleのデータソースプロパティ(UT)を生成する. * @return Oracleのデータソースプロパティ(UT) */ @Bean(name = {"datasourceOraProperties"}) @Primary @ConfigurationProperties(prefix = "spring.datasourceut-ora") public DataSourceProperties datasourceOraProperties() { return new DataSourceProperties(); } /** * Oracleのデータソース(UT)を生成する. * @param properties Oracleのデータソースプロパティ(UT) * @return Oracleのデータソース(UT) */ @Bean(name = {"dataSourceOra"}) @Primary public DataSource datasourceOra( @Qualifier("datasourceOraProperties") DataSourceProperties properties) { return properties.initializeDataSourceBuilder().build(); } /** * Oracleのトランザクションマネージャ(UT)を生成する. * @param dataSourceOra Oracleのデータソース(UT) * @return Oracleのトランザクションマネージャ(UT) */ @Bean(name = {"txManagerOra"}) @Primary public PlatformTransactionManager txManagerOra( @Qualifier("dataSourceOra") DataSource dataSourceOra) { return new DataSourceTransactionManager(dataSourceOra); } /** * OracleのDB接続設定(UT)を生成する. * @return OracleのDB接続設定(UT) */ @Bean(name = {"dbUnitDatabaseConfigOra"}) public DatabaseConfigBean dbUnitDatabaseConfigOra() { DatabaseConfigBean bean = new DatabaseConfigBean(); bean.setAllowEmptyFields(true); bean.setDatatypeFactory(new Oracle10DataTypeFactory()); return bean; } /** * Oracleのデータソースコネクションファクトリ(UT)を生成する. * @param dbUnitDatabaseConfigOra OracleのDB接続設定(UT) * @param dataSourceOra Oracleのデータソース(UT) * @return Oracleのデータソースコネクションファクトリ(UT) */ @Bean(name = {"dbUnitDatabaseConnectionOra"}) public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnectionOra( @Qualifier("dbUnitDatabaseConfigOra") DatabaseConfigBean dbUnitDatabaseConfigOra, @Qualifier("dataSourceOra") DataSource dataSourceOra) { DatabaseDataSourceConnectionFactoryBean bean = new DatabaseDataSourceConnectionFactoryBean(dataSourceOra); bean.setDatabaseConfig(dbUnitDatabaseConfigOra); bean.setSchema("USER01"); return bean; } } |
さらに、Mapperのテストクラスの内容は以下の通りで、truncate table文とその実行前後のデータを取得している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | package com.example.demo.mapper.ora; import com.example.demo.mapper.DemoXlsDataSetLoader; import com.example.demo.mapper.UserData; import com.github.springtestdbunit.DbUnitTestExecutionListener; import com.github.springtestdbunit.TransactionDbUnitTestExecutionListener; import com.github.springtestdbunit.annotation.DbUnitConfiguration; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import java.util.List; import static org.junit.Assert.assertEquals; // JUnit5ベースでMyBatisのテストを実行する @MybatisTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestExecutionListeners({DependencyInjectionTestExecutionListener.class , DirtiesContextTestExecutionListener.class , TransactionDbUnitTestExecutionListener.class , DbUnitTestExecutionListener.class}) @DbUnitConfiguration(dataSetLoader = DemoXlsDataSetLoader.class , databaseConnection = {"dbUnitDatabaseConnectionOra"}) public class UserDataTruncateTestOra { /** * ユーザーデータテーブル(user_data)へアクセスするマッパー */ @Autowired private UserDataMapperOra userDataMapperOra; /** * 各テストメソッドを実行する前に行う処理を定義する. */ @BeforeEach public void beforeTest() { System.out.println(); System.out.println("*** UserDataTruncateTestOraクラス テスト結果 start ***"); } /** * truncate文の実行結果を検証する. */ @Test public void userDataTest() { // ユーザーデータ削除する前のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate前 ***"); List<UserData> userDataList = userDataMapperOra.findAll(); for (UserData userData : userDataList) { System.out.println(userData); } // ユーザーデータを削除 userDataMapperOra.truncateUserData(); // ユーザーデータ削除した後のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate後 ***"); userDataList = userDataMapperOra.findAll(); System.out.println(userDataList); assertEquals(0, userDataList.size()); } /** * 各テストメソッドを実行した後に行う処理を定義する. */ @AfterEach public void afterTestClass() { System.out.println("*** UserDataTruncateTestOraクラス テスト結果 end ***"); System.out.println(); } } |
上記テストクラスの実行結果は以下の通りで、truncate table文の実行でコミットされていることが確認できる。
MySQLの場合のソースコードとテスト実行結果
テスト対象となるMapperの内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.example.demo.mapper.ms; import com.example.demo.mapper.UserData; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserDataMapperMs { /** * MySQLでユーザーデータテーブル(user_data)の全データを取得する * @return ユーザーデータテーブル(user_data)の全データ */ List<UserData> findAll(); /** * MySQLでユーザーデータテーブル(user_data)の全データを削除する */ void truncateUserData(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?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.mapper.ms.UserDataMapperMs"> <resultMap id="userDataResultMap" type="com.example.demo.mapper.UserData" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="birthY" property="birthY" jdbcType="VARCHAR" /> <result column="birthM" property="birthM" jdbcType="VARCHAR" /> <result column="birthD" property="birthD" jdbcType="VARCHAR" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="memo" property="memo" jdbcType="VARCHAR" /> <result column="sex_value" property="sex_value" jdbcType="VARCHAR" /> </resultMap> <select id="findAll" resultMap="userDataResultMap"> SELECT id , name , birth_year as birthY , birth_month as birthM , birth_day as birthD , sex , memo , CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '' END AS sex_value FROM USER_DATA </select> <update id="truncateUserData"> TRUNCATE TABLE USER_DATA </update> </mapper> |
また、JUnit5 DBUnitで利用するDB接続先設定の内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | package com.example.demo.mapper.ms; import com.github.springtestdbunit.bean.DatabaseConfigBean; import com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean; import org.dbunit.ext.mysql.MySqlDataTypeFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; // MyBatisのテストを実行する際のDB接続定義 // @MybatisTestアノテーションでテストを実行する際、 // Spring Bootアプリケーションが起動するようにする。 // その際、com.example.demo.mapper.msフォルダ下のインスタンス // (UserDataMapper)のみがDIで使用できるようになる。 @SpringBootApplication @PropertySource(value = {"classpath:test.properties"}) public class DemoTestMsConfig { /** * MySQLのデータソースプロパティ(UT)を生成する. * @return MySQLのデータソースプロパティ(UT) */ @Bean(name = {"datasourceMsProperties"}) @Primary @ConfigurationProperties(prefix = "spring.datasourceut-ms") public DataSourceProperties datasourceMsProperties() { return new DataSourceProperties(); } /** * MySQLのデータソース(UT)を生成する. * @param properties MySQLのデータソースプロパティ(UT) * @return MySQLのデータソース(UT) */ @Bean(name = {"dataSourceMs"}) @Primary public DataSource datasourceMs( @Qualifier("datasourceMsProperties") DataSourceProperties properties) { return properties.initializeDataSourceBuilder().build(); } /** * MySQLのトランザクションマネージャ(UT)を生成する. * @param dataSourceMs MySQLのデータソース(UT) * @return MySQLのトランザクションマネージャ(UT) */ @Bean(name = {"txManagerMs"}) @Primary public PlatformTransactionManager txManagerMs( @Qualifier("dataSourceMs") DataSource dataSourceMs) { return new DataSourceTransactionManager(dataSourceMs); } /** * MySQLのDB接続設定(UT)を生成する. * @return MySQLのDB接続設定(UT) */ @Bean(name = {"dbUnitDatabaseConfigMs"}) public DatabaseConfigBean dbUnitDatabaseConfigMs() { DatabaseConfigBean bean = new DatabaseConfigBean(); bean.setAllowEmptyFields(true); bean.setDatatypeFactory(new MySqlDataTypeFactory()); return bean; } /** * MySQLのデータソースコネクションファクトリ(UT)を生成する. * @param dbUnitDatabaseConfigMs MySQLのDB接続設定(UT) * @param dataSourceMs MySQLのデータソース(UT) * @return MySQLのデータソースコネクションファクトリ(UT) */ @Bean(name = {"dbUnitDatabaseConnectionMs"}) public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnectionOra( @Qualifier("dbUnitDatabaseConfigMs") DatabaseConfigBean dbUnitDatabaseConfigMs, @Qualifier("dataSourceMs") DataSource dataSourceMs) { DatabaseDataSourceConnectionFactoryBean bean = new DatabaseDataSourceConnectionFactoryBean(dataSourceMs); bean.setDatabaseConfig(dbUnitDatabaseConfigMs); return bean; } } |
さらに、Mapperのテストクラスの内容は以下の通りで、truncate table文とその実行前後のデータを取得している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | package com.example.demo.mapper.ms; import com.example.demo.mapper.DemoXlsDataSetLoader; import com.example.demo.mapper.UserData; import com.github.springtestdbunit.DbUnitTestExecutionListener; import com.github.springtestdbunit.TransactionDbUnitTestExecutionListener; import com.github.springtestdbunit.annotation.DbUnitConfiguration; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import java.util.List; import static org.junit.Assert.assertEquals; // JUnit5ベースでMyBatisのテストを実行する @MybatisTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestExecutionListeners({DependencyInjectionTestExecutionListener.class , DirtiesContextTestExecutionListener.class , TransactionDbUnitTestExecutionListener.class , DbUnitTestExecutionListener.class}) @DbUnitConfiguration(dataSetLoader = DemoXlsDataSetLoader.class , databaseConnection = {"dbUnitDatabaseConnectionMs"}) public class UserDataTruncateTestMs { /** * ユーザーデータテーブル(user_data)へアクセスするマッパー */ @Autowired private UserDataMapperMs userDataMapperMs; /** * 各テストメソッドを実行する前に行う処理を定義する. */ @BeforeEach public void beforeTest() { System.out.println(); System.out.println("*** UserDataTruncateTestMsクラス テスト結果 start ***"); } /** * truncate文の実行結果を検証する. */ @Test public void userDataTest() { // ユーザーデータ削除する前のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate前 ***"); List<UserData> userDataList = userDataMapperMs.findAll(); for (UserData userData : userDataList) { System.out.println(userData); } System.out.println(); // ユーザーデータを削除 userDataMapperMs.truncateUserData(); // ユーザーデータ削除した後のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate後 ***"); userDataList = userDataMapperMs.findAll(); System.out.println(userDataList); assertEquals(0, userDataList.size()); } /** * 各テストメソッドを実行した後に行う処理を定義する. */ @AfterEach public void afterTestClass() { System.out.println("*** UserDataTruncateTestMsクラス テスト結果 end ***"); System.out.println(); } } |
上記テストクラスの実行結果は以下の通りで、truncate table文の実行でコミットされていることが確認できる。
PostgreSQLの場合のソースコードとテスト実行結果
テスト対象となるMapperの内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.example.demo.mapper.ps; import com.example.demo.mapper.UserData; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserDataMapperPs { /** * PostgreSQLでユーザーデータテーブル(user_data)の全データを取得する * @return ユーザーデータテーブル(user_data)の全データ */ List<UserData> findAll(); /** * PostgreSQLでユーザーデータテーブル(user_data)の全データを削除する */ void truncateUserData(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?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.mapper.ps.UserDataMapperPs"> <resultMap id="userDataResultMap" type="com.example.demo.mapper.UserData" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="birthY" property="birthY" jdbcType="VARCHAR" /> <result column="birthM" property="birthM" jdbcType="VARCHAR" /> <result column="birthD" property="birthD" jdbcType="VARCHAR" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="memo" property="memo" jdbcType="VARCHAR" /> <result column="sex_value" property="sex_value" jdbcType="VARCHAR" /> </resultMap> <select id="findAll" resultMap="userDataResultMap"> SELECT id , name , birth_year as birthY , birth_month as birthM , birth_day as birthD , sex , memo , CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '' END AS sex_value FROM USER_DATA </select> <update id="truncateUserData"> TRUNCATE TABLE USER_DATA </update> </mapper> |
また、JUnit5 DBUnitで利用するDB接続先設定の内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | package com.example.demo.mapper.ps; import com.github.springtestdbunit.bean.DatabaseConfigBean; import com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean; import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; // MyBatisのテストを実行する際のDB接続定義 // @MybatisTestアノテーションでテストを実行する際、 // Spring Bootアプリケーションが起動するようにする。 // その際、com.example.demo.mapper.oraフォルダ下のインスタンス // (UserDataMapper)のみがDIで使用できるようになる。 @SpringBootApplication @PropertySource(value = {"classpath:test.properties"}) public class DemoTestPsConfig { /** * PostgreSQLのデータソースプロパティ(UT)を生成する. * @return PostgreSQLのデータソースプロパティ(UT) */ @Bean(name = {"datasourcePsProperties"}) @Primary @ConfigurationProperties(prefix = "spring.datasourceut-ps") public DataSourceProperties datasourcePsProperties() { return new DataSourceProperties(); } /** * PostgreSQLのデータソース(UT)を生成する. * @param properties PostgreSQLのデータソースプロパティ(UT) * @return PostgreSQLのデータソース(UT) */ @Bean(name = {"dataSourcePs"}) @Primary public DataSource datasourcePs( @Qualifier("datasourcePsProperties") DataSourceProperties properties) { return properties.initializeDataSourceBuilder().build(); } /** * PostgreSQLのトランザクションマネージャ(UT)を生成する. * @param dataSourcePs PostgreSQLのデータソース(UT) * @return PostgreSQLのトランザクションマネージャ(UT) */ @Bean(name = {"txManagerPs"}) @Primary public PlatformTransactionManager txManagerPs( @Qualifier("dataSourcePs") DataSource dataSourcePs) { return new DataSourceTransactionManager(dataSourcePs); } /** * PostgreSQLのDB接続設定(UT)を生成する. * @return PostgreSQLのDB接続設定(UT) */ @Bean(name = {"dbUnitDatabaseConfigPs"}) public DatabaseConfigBean dbUnitDatabaseConfigPs() { DatabaseConfigBean bean = new DatabaseConfigBean(); bean.setAllowEmptyFields(true); bean.setDatatypeFactory(new PostgresqlDataTypeFactory()); return bean; } /** * PostgreSQLのデータソースコネクションファクトリ(UT)を生成する. * @param dbUnitDatabaseConfigPs PostgreSQLのDB接続設定(UT) * @param dataSourcePs PostgreSQLのデータソース(UT) * @return PostgreSQLのデータソースコネクションファクトリ(UT) */ @Bean(name = {"dbUnitDatabaseConnectionPs"}) public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnectionPs( @Qualifier("dbUnitDatabaseConfigPs") DatabaseConfigBean dbUnitDatabaseConfigPs, @Qualifier("dataSourcePs") DataSource dataSourcePs) { DatabaseDataSourceConnectionFactoryBean bean = new DatabaseDataSourceConnectionFactoryBean(dataSourcePs); bean.setDatabaseConfig(dbUnitDatabaseConfigPs); return bean; } } |
さらに、Mapperのテストクラスの内容は以下の通りで、truncate table文とその実行前後のデータを取得している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | package com.example.demo.mapper.ps; import com.example.demo.mapper.DemoXlsDataSetLoader; import com.example.demo.mapper.UserData; import com.github.springtestdbunit.DbUnitTestExecutionListener; import com.github.springtestdbunit.TransactionDbUnitTestExecutionListener; import com.github.springtestdbunit.annotation.DbUnitConfiguration; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import java.util.List; import static org.junit.Assert.assertEquals; // JUnit5ベースでMyBatisのテストを実行する @MybatisTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestExecutionListeners({DependencyInjectionTestExecutionListener.class , DirtiesContextTestExecutionListener.class , TransactionDbUnitTestExecutionListener.class , DbUnitTestExecutionListener.class}) @DbUnitConfiguration(dataSetLoader = DemoXlsDataSetLoader.class , databaseConnection = {"dbUnitDatabaseConnectionPs"}) public class UserDataTruncateTestPs { /** * ユーザーデータテーブル(user_data)へアクセスするマッパー */ @Autowired private UserDataMapperPs userDataMapperPs; /** * 各テストメソッドを実行する前に行う処理を定義する. */ @BeforeEach public void beforeTest() { System.out.println(); System.out.println("*** UserDataTruncateTestPsクラス テスト結果 start ***"); } /** * truncate文の実行結果を検証する. */ @Test public void userDataTest() { // ユーザーデータ削除する前のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate前 ***"); List<UserData> userDataList = userDataMapperPs.findAll(); for (UserData userData : userDataList) { System.out.println(userData); } // ユーザーデータを削除 userDataMapperPs.truncateUserData(); // ユーザーデータ削除した後のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate後 ***"); userDataList = userDataMapperPs.findAll(); System.out.println(userDataList); assertEquals(0, userDataList.size()); } /** * 各テストメソッドを実行した後に行う処理を定義する. */ @AfterEach public void afterTestClass() { System.out.println("*** UserDataTruncateTestPsクラス テスト結果 end ***"); System.out.println(); } } |
上記テストクラスの実行結果は以下の通りで、truncate table文の実行でロールバックされていることが確認できる。
SQL Serverの場合のソースコードとテスト実行結果
テスト対象となるMapperの内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.example.demo.mapper.ss; import com.example.demo.mapper.UserData; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserDataMapperSs { /** * SQL Serverでユーザーデータテーブル(user_data)の全データを取得する * @return ユーザーデータテーブル(user_data)の全データ */ List<UserData> findAll(); /** * SQL Serverでユーザーデータテーブル(user_data)の全データを削除する */ void truncateUserData(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?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.mapper.ss.UserDataMapperSs"> <resultMap id="userDataResultMap" type="com.example.demo.mapper.UserData" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="birthY" property="birthY" jdbcType="VARCHAR" /> <result column="birthM" property="birthM" jdbcType="VARCHAR" /> <result column="birthD" property="birthD" jdbcType="VARCHAR" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="memo" property="memo" jdbcType="VARCHAR" /> <result column="sex_value" property="sex_value" jdbcType="VARCHAR" /> </resultMap> <select id="findAll" resultMap="userDataResultMap"> SELECT id , name , birth_year as birthY , birth_month as birthM , birth_day as birthD , sex , memo , CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '' END AS sex_value FROM dbo.USER_DATA </select> <update id="truncateUserData"> TRUNCATE TABLE dbo.USER_DATA </update> </mapper> |
また、JUnit5 DBUnitで利用するDB接続先設定の内容は、以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | package com.example.demo.mapper.ss; import com.github.springtestdbunit.bean.DatabaseConfigBean; import com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean; import org.dbunit.ext.mssql.MsSqlDataTypeFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; // MyBatisのテストを実行する際のDB接続定義 // @MybatisTestアノテーションでテストを実行する際、 // Spring Bootアプリケーションが起動するようにする。 // その際、com.example.demo.mapper.oraフォルダ下のインスタンス // (UserDataMapper)のみがDIで使用できるようになる。 @SpringBootApplication @PropertySource(value = {"classpath:test.properties"}) public class DemoTestSsConfig { /** * SQLServerのデータソースプロパティ(UT)を生成する. * @return SQLServerのデータソースプロパティ(UT) */ @Bean(name = {"datasourceSsProperties"}) @Primary @ConfigurationProperties(prefix = "spring.datasourceut-ss") public DataSourceProperties datasourceSsProperties() { return new DataSourceProperties(); } /** * SQLServerのデータソース(UT)を生成する. * @param properties SQLServerのデータソースプロパティ(UT) * @return SQLServerのデータソース(UT) */ @Bean(name = {"dataSourceSs"}) @Primary public DataSource datasourceSs( @Qualifier("datasourceSsProperties") DataSourceProperties properties) { return properties.initializeDataSourceBuilder().build(); } /** * SQLServerのトランザクションマネージャ(UT)を生成する. * @param dataSourceSs SQLServerのデータソース(UT) * @return SQLServerのトランザクションマネージャ(UT) */ @Bean(name = {"txManagerSs"}) @Primary public PlatformTransactionManager txManagerSs( @Qualifier("dataSourceSs") DataSource dataSourceSs) { return new DataSourceTransactionManager(dataSourceSs); } /** * SQLServerのDB接続設定(UT)を生成する. * @return SQLServerのDB接続設定(UT) */ @Bean(name = {"dbUnitDatabaseConfigSs"}) public DatabaseConfigBean dbUnitDatabaseConfigSs() { DatabaseConfigBean bean = new DatabaseConfigBean(); bean.setAllowEmptyFields(true); bean.setDatatypeFactory(new MsSqlDataTypeFactory()); return bean; } /** * SQLServerのデータソースコネクションファクトリ(UT)を生成する. * @param dbUnitDatabaseConfigSs SQLServerのDB接続設定(UT) * @param dataSourceSs SQLServerのデータソース(UT) * @return SQLServerのデータソースコネクションファクトリ(UT) */ @Bean(name = {"dbUnitDatabaseConnectionSs"}) public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnectionSs( @Qualifier("dbUnitDatabaseConfigSs") DatabaseConfigBean dbUnitDatabaseConfigSs, @Qualifier("dataSourceSs") DataSource dataSourceSs) { DatabaseDataSourceConnectionFactoryBean bean = new DatabaseDataSourceConnectionFactoryBean(dataSourceSs); bean.setDatabaseConfig(dbUnitDatabaseConfigSs); return bean; } } |
さらに、Mapperのテストクラスの内容は以下の通りで、truncate table文とその実行前後のデータを取得している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | package com.example.demo.mapper.ss; import com.example.demo.mapper.DemoXlsDataSetLoader; import com.example.demo.mapper.UserData; import com.github.springtestdbunit.DbUnitTestExecutionListener; import com.github.springtestdbunit.TransactionDbUnitTestExecutionListener; import com.github.springtestdbunit.annotation.DbUnitConfiguration; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import java.util.List; import static org.junit.Assert.assertEquals; // JUnit5ベースでMyBatisのテストを実行する @MybatisTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestExecutionListeners({DependencyInjectionTestExecutionListener.class , DirtiesContextTestExecutionListener.class , TransactionDbUnitTestExecutionListener.class , DbUnitTestExecutionListener.class}) @DbUnitConfiguration(dataSetLoader = DemoXlsDataSetLoader.class , databaseConnection = {"dbUnitDatabaseConnectionSs"}) public class UserDataTruncateTestSs { /** * ユーザーデータテーブル(user_data)へアクセスするマッパー */ @Autowired private UserDataMapperSs userDataMapperSs; /** * 各テストメソッドを実行する前に行う処理を定義する. */ @BeforeEach public void beforeTest() { System.out.println(); System.out.println("*** UserDataTruncateTestSsクラス テスト結果 start ***"); } /** * truncate文の実行結果を検証する. */ @Test public void userDataTest() { // ユーザーデータ削除する前のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate前 ***"); List<UserData> userDataList = userDataMapperSs.findAll(); for (UserData userData : userDataList) { System.out.println(userData); } // ユーザーデータを削除 userDataMapperSs.truncateUserData(); // ユーザーデータ削除した後のデータを確認 System.out.println("*** ユーザーデータテーブル(user_data)のデータ Truncate後 ***"); userDataList = userDataMapperSs.findAll(); System.out.println(userDataList); assertEquals(0, userDataList.size()); } /** * 各テストメソッドを実行した後に行う処理を定義する. */ @AfterEach public void afterTestClass() { System.out.println("*** UserDataTruncateTestSsクラス テスト結果 end ***"); System.out.println(); } } |
上記テストクラスの実行結果は以下の通りで、truncate table文の実行でロールバックされていることが確認できる。
要点まとめ
- JUnit5 DBUnitを利用して、truncate table文を実行すると、OracleとMySQLの場合はコミットされ、PostgreSQLとSQL Serverの場合はロールバックされることが確認できる。