はじめに
Testcontainersを使ってMySQLへのCRUDを行うデータアクセスロジックのテストコードを書いてみたので備忘録を残します。本記事内では抜粋したサンプルコードを掲載していますが、完全なソースコードはGitHubリポジトリで閲覧可能です。
Testcontainersとは
公式リファレンスでは以下のように説明されています。
Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
(訳:TestcontainersはJUnitテストをサポートするJavaライブラリで、一般的なデータベースやSeleniumウェブブラウザなど、Dockerコンテナで実行可能なあらゆるものの軽量で使い捨てのインスタンスを提供します。)
つまり、データベースのような外部へのアクセスを伴うテストを行う際、そのアクセス先をテスト実行時のみ有効なDockerコンテナで代用することができるようになり、以下のようなメリットが得られます。
- アクセス先を開発用ローカルマシン内に立ち上げたり、ローカルネットワーク内に立ち上げたりする必要が無くなる
- テストコードや設定ファイルを共有するだけで同じテスト環境を共有できる
- テスト実施時はアクセス先が毎回同じ状態であることが保証される
- テスト終了後はコンテナが破棄され、テストの影響が残らない
今回は、単体テストコードからTestcontainersにより生成されたDockerコンテナ内のMySQLにアクセスし、実際のMySQLデータベースを用意することなくテストを実施できるようにします。
ここで解説する内容の多くは、JDBCを用いる場合であればMySQL以外のDBイメージにも共通の内容です。また、TestcontainersではDB以外にも、多くのDockerイメージに対応しています。利用可能なイメージの一覧は、公式リファレンスの「Modules」を参照してください。
環境
- Java
- Junit5
- Spring Boot
- MyBatis
- Maven
- Windows10(※Testcontainers実行時はDocker Desktopを起動しておく必要があります)
依存関係
JUnit5でTestcontainersを利用するための依存関係としてorg.testcontainers:junit-jupiter
を、TestcontainersでMySQLイメージを利用するための依存関係としてをorg.testcontainers:mysql
それぞれ<dependencies>
に追加する必要があります。また、Testcontainersで使用するDBイメージを依存関係に追加していても、そのDB用のJDBCドライバは別途クラスパス上に存在する必要があるため、MySQL用のJDBCドライバも<dependencies>
に追加します。
<dependencies>
...
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.16.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>1.16.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<!-- Spring Boot利用のためバージョンは省略 -->
</dependency>
...
</dependencies>
公式リファレンスではそれぞれの依存関係で個別に<version>
を明示する代わりに、<dependencyManagement>
にTestcontainersのBOMを追加することを推奨しています。
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>1.16.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
...
</dependencies>
</dependencyManagement>
<dependencies>
...
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<!-- <version>1.16.2</version> BOM利用時は省略可-->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<!-- <version>1.16.2</version> BOM利用時は省略可-->
<scope>test</scope>
</dependency>
...
</dependencies>
BOMを追加することで、それぞれのTestcontainers依存関係のバージョンはBOMのバージョンに対応するものが自動的に選択されます。
コンテナの生成方法
Testcontainersでテストコードからアクセス可能なMySQLコンテナを生成するための方法として、公式リファレンスでは以下の2つが提示されています。
1. Testcontainers用JDBC URLを使用しコンテナの生成を指示する方法
2. Database container objectsを使用しテストコード内で明示的にコンテナを生成する方法
公式リファレンスでは1.Testcontainers用JDBC URLを用いる方法をまず検討し、その方法が採用できない制約がある場合や、DBコンテナを細かく設定したい場合に2.Database container objectsを用いる方法を採用するよう推奨しています。
今回は1.Testcontainers用JDBC URLを用いた方法を採用しました。
また、詳細は後述しますが、1.Testcontainers用JDBC URLを用いる方法ではテストコード内にコンテナを生成するための処理を記述する必要が無く、Testcontainers用JDBC URLを実際に接続するDB用のJDBC URLに変更すれば、そのまま実際のDBを使用したテストに切り替えることもできます。
Testcontainers用JDBC URLの形式
実際のJDBC URLを以下の手順で修正することでTestcontainers形式のJDBC URLになり、テスト実行時に指定したイメージのDBコンテナが生成されるようになります。Spring Bootを使用している今回の例であれば、spring.datasource.url
プロパティにTestcontainers用JDBC URLを指定すると、Testcontainersが有効になります。
-
jdbc:
の後ろにtc:
を挿入する -
ドライバ名
をDockerイメージ名:タグ名
に置き換える
- jdbc:mysql://localhost:3306/databasename
+ jdbc:tc:mysql:8.0://localhost:3306/databasename
(「tc」を挿入し、「mysql」というドライバ名を「mysql:8.0」というDockerイメージ名に置換)
また、Testcontainers用JDBC URL内ではホスト名:ポート番号/データベース名
は無視されるので、最終的に以下のように短縮できます。
- jdbc:tc:mysql:8.0://localhost:3306/databasename
+ jdbc:tc:mysql:8.0:///
(「ホスト名:ポート番号/データベース名」を除去)
この短縮形式をhost-less URIs
と呼びます。
jdbc:tc:[Dockerイメージ名]:[タグ名]///
JDBC URLを見たとき、Testcontainersを使用していることがすぐに分かるため、テスト用のJDBC URLにはhost-less URIs
を使うことをお勧めします。
TestcontainersではJDBC URLの短縮有無によらず、生成されるコンテナのデータベース名,使用されるユーザー名やパスワードは一律test
に固定されます。これらを変更したい場合は、前述のDatabase container objectsによりコンテナを生成してください。
公式リファレンス内の解説では、
Note that the hostname, port and database name will be ignored;(訳: ホスト名,ポート番号,DB名は無視されます)
と明記されているにもかかわらず、jdbc:mysql:8.0:///databasename
のようにDB名のみを指定したJDBC URLが例示されていますが、2022/02現在、指定したDB名は生成されるコンテナに反映されません。GitHubのissueでこの点について議論されています。
オプションの指定方法
Testcontainers用JDBC URLには、クエリパラメータ形式でオプションを指定することができます。複数のオプションを指定する場合もクエリパラメータの形式同様に&
で連結します。
オプションの種類はいくつかありますが、ここではTC_INITSCRIPT
について解説します。その他のオプションについては公式リファレンスを参照してください。DBイメージで固有のオプション等も存在します。
TC_INITSCRIPT
テストコードの実行前に、生成されたDBコンテナを初期化するためのSQLファイルを実行させるためのオプションです。Testcontainersにより生成されたDBコンテナは空っぽの状態で、テーブルもテスト用データも含まれていません。そのため、このオプションを用いてDDLやテストデータの投入を行うSQLをあらかじめ実行しておくよう指示します。
このオプションを使用するためには、Testcontainers用JDBC URLにクエリパラメータとして
TC_INITSCRIPT=[初期化用SQLファイルのパス]
を付加します。パスは「クラスパスルートからの相対パス」で指定してください。
jdbc:tc:mysql:8.0:///?TC_INITSCRIPT=path/to/ddl.sql
(DBコンテナ生成後に、「ddl.sql」というSQLファイルを実行させる場合の例)
テストコードの記述方法
実際にTestcontainersにより生成されるDBコンテナを使用するテストコードを記述する方法について解説します。
初めにサンプルテストコードを掲載し、それぞれのポイントについて解説していきます。
@Testcontainers // (1)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // (2)
@MybatisTest // (3)
@Sql("classpath:path/to/testdata.sql") // (4)
class UserDaoTest {
@Autowired
private UserDao dao;
@Test
void testUserDao() {
// (5)
}
}
(1) @Testcontainers
テストクラスでTestcontainersにより生成されるDockerコンテナを使用することを宣言するためのアノテーションです。テストクラスにこのアノテーションを付与することで、テスト実行前にJDBC URLに基づき、DBコンテナが生成・初期化されます。
@Testcontainers(disabledWithoutDocker = true)
のようにdisableWithoutDocker
パラメータにtrue
を指定すると、テスト実行時にDockerが利用できなかった場合はテストがスキップされるようになります。(WindowsPCを使っている場合、Docker Desktopを起動せずにテストを実行するとテストがスキップされることが確認できます。)
(2) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
Spring Bootでデフォルトで有効になっているテスト用組込DBを無効化するためのアノテーションです。本アノテーションを付与する代わりに、spring.test.database.replace
プロパティにnone
を指定することでも同様の効果があります。
(3) @MybatisTest
今回はO/RマッパーとしてMyBatisを使用するため、テストコード内でMyBatis関連のAutoConfigureクラス,MapperクラスのBeanのみが有効になるよう本アノテーションを付与しています。
@MyBatisTest
については、こちらの記事を参照してください。
(4) @Sql
各テストメソッド実行前に、指定されたSQLファイルを実行してくれるアノテーションです。DBコンテナにテストデータを投入する用途で使用しています。
前述のTC_INITSCRIPT
オプションでもSQLファイルを用いたDBコンテナの初期化を行うことができますが、TC_INITSCRIPT
オプションではSQLファイルを1つしか指定することができません。そのため、DDLとテストデータ投入を1つのSQLファイル内に記述する必要があります。
DDLとテストデータ投入は別のSQLファイルで管理したい場合や、テストケースに応じて投入するテストデータを切り替えたい場合は、本サンプルのように@Sql
アノテーションでテストデータの投入を行っています。その他、DBUnitなどのツールもTestcontainersと併用可能です。
(5) テストメソッドの実装
各テストメソッド内ではTestcontainersを意識することなく、実際のDBを用いる場合と全く同じようにテストコードを記述することができます。
プロパティファイルの記述方法
本サンプルではSpring Bootを用いているので、Testcontainersに関するプロパティファイルの記述についても解説します。
spring.datasource.url=${DATASOURCE:jdbc:tc:mysql:8.0:///?TC_INITSCRIPT=path/to/ddl.sql}
spring.datasource.username=${DATASOURCE_USER:}
spring.datasource.password=${DATASOURCE_PASSWORD:}
spring.test.database.replace=none
spring.datasource.url
Testcontainers用JDBC URLを指定します。
このサンプルでは${環境変数名:デフォルト値}
の形式でプロパティ値を指定しており、環境変数DATASOURCE
に値が設定されていればその値をJDBC URLとして使用し、設定されていなければTestcontainers用JDBC URLを使用するようになっています。
JDBC URLがTestcontainers用の形式でなければ、テストクラスに前述の@Testcontainers
アノテーションが付与されていてもDBコンテナの生成は行われません。そのため、ステージング環境などでは環境変数を設定しておくことで実際のDBを用いたテストを行い、ローカル環境ではDBコンテナを用いたテストを行うというようなことが、テストコードを修正したり複数用意したりすることなく実現できます。
spring.datasource.username,spring.datasource.password
こちらも${環境変数:デフォルト値}
の形式ですが、デフォルト値を指定していません。前述のとおり、Testcontainers用JDBC URL使用時はユーザー名やパスワードはtest
で固定されますが、他の値を指定したり、あるいは何も指定しなくても認証エラーにはならないので、このようにプロパティ値を指定しています。
spring.test.database.replace
Spring Bootでデフォルトで有効になっているテスト用組込DBを無効化するための指定です。
前述した@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
アノテーションを使う代わりに、プロパティファイルで設定する場合の記述です。
テスト実行
通常のテストと同様に、EclipseやMavenで実行することができます。
以下はテストを実行した際に出力されるログです。(指定したDockerイメージをTestcontainersで初めて使用する場合は数分以上時間がかかります。)
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.2)
2022-01-31 10:55:26.500 INFO 16468 --- [ main] com.example.UserDaoTest : Starting UserDaoTest using Java 17.0.1 on with PID 16468 (started by)
2022-01-31 10:55:26.502 INFO 16468 --- [ main] com.example.UserDaoTest : No active profile set, falling back to default profiles: default
2022-01-31 10:55:27.819 INFO 16468 --- [ main] com.example.UserDaoTest : Started UserDaoTest in 1.891 seconds (JVM running for 3.261)
2022-01-31 10:55:27.868 INFO 16468 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2022-01-31 10:55:28.130 INFO 16468 --- [ main] o.t.d.DockerClientProviderStrategy : Loaded org.testcontainers.dockerclient.NpipeSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
2022-01-31 10:55:28.723 INFO 16468 --- [ main] o.t.d.DockerClientProviderStrategy : Found Docker environment with local Npipe socket (npipe:////./pipe/docker_engine)
2022-01-31 10:55:28.725 INFO 16468 --- [ main] org.testcontainers.DockerClientFactory : Docker host IP address is localhost
2022-01-31 10:55:28.779 INFO 16468 --- [ main] org.testcontainers.DockerClientFactory : Connected to docker:
Server Version: 20.10.11
API Version: 1.41
Operating System: Docker Desktop
Total Memory: 4711 MB
2022-01-31 10:55:28.784 INFO 16468 --- [ main] o.t.utility.ImageNameSubstitutor : Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
2022-01-31 10:55:29.215 INFO 16468 --- [ main] o.t.utility.RegistryAuthLocator : Credential helper/store (docker-credential-desktop) does not have credentials for index.docker.io
2022-01-31 10:55:32.569 INFO 16468 --- [ main] org.testcontainers.DockerClientFactory : Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
2022-01-31 10:55:32.570 INFO 16468 --- [ main] org.testcontainers.DockerClientFactory : Checking the system...
2022-01-31 10:55:32.571 INFO 16468 --- [ main] org.testcontainers.DockerClientFactory : ✔︎ Docker server version should be at least 1.6.0
2022-01-31 10:55:32.706 INFO 16468 --- [ main] org.testcontainers.DockerClientFactory : ✔︎ Docker environment should have more than 2GB free disk space
2022-01-31 10:55:32.725 INFO 16468 --- [ main] 🐳 [mysql:8.0] : Creating container for image: mysql:8.0
2022-01-31 10:55:32.879 INFO 16468 --- [ main] 🐳 [mysql:8.0] : Starting container with ID: 466df4de50fe211466427c0c56d673ba8ebb9b4edbf8f124eb654560614bb8a2
2022-01-31 10:55:33.253 INFO 16468 --- [ main] 🐳 [mysql:8.0] : Container mysql:8.0 is starting: 466df4de50fe211466427c0c56d673ba8ebb9b4edbf8f124eb654560614bb8a2
2022-01-31 10:55:33.325 INFO 16468 --- [ main] 🐳 [mysql:8.0] : Waiting for database connection to become available at jdbc:mysql://localhost:62119/test using query 'SELECT 1'
2022-01-31 10:55:48.318 INFO 16468 --- [ main] 🐳 [mysql:8.0] : Container is started (JDBC URL: jdbc:mysql://localhost:62119/test)
2022-01-31 10:55:48.318 INFO 16468 --- [ main] 🐳 [mysql:8.0] : Container mysql:8.0 started in PT15.6056995S
2022-01-31 10:55:48.353 INFO 16468 --- [ main] org.testcontainers.ext.ScriptUtils : Executing database script from META-INF/mysql/ddl.sql
2022-01-31 10:55:48.406 INFO 16468 --- [ main] org.testcontainers.ext.ScriptUtils : Executed database script from META-INF/mysql/ddl.sql in 52 ms.
2022-01-31 10:55:48.420 INFO 16468 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2022-01-31 10:55:48.430 INFO 16468 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@3576ddc2 testClass = UserDaoTest, testInstance = com.example.UserDaoTest@cd1e646, testMethod = testDelete@UserDaoTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@35b74c5c testClass = UserDaoTest, locations = '{}', classes = '{class com.example.DemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.mybatis.spring.boot.test.autoconfigure.MybatisTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@2e570ded key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@61001b64, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@26e356f0, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@272113c4, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@3f6f6701, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@9647a2c9, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@13e344d, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.jdbc.support.JdbcTransactionManager@73608eb0]; rollback [true]
2022-01-31 10:55:49.394 INFO 16468 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@3576ddc2 testClass = UserDaoTest, testInstance = com.example.UserDaoTest@cd1e646, testMethod = testDelete@UserDaoTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@35b74c5c testClass = UserDaoTest, locations = '{}', classes = '{class com.example.DemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.mybatis.spring.boot.test.autoconfigure.MybatisTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@2e570ded key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@61001b64, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@26e356f0, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@272113c4, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@3f6f6701, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@9647a2c9, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@13e344d, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]
2022-01-31 10:55:49.411 INFO 16468 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@3576ddc2 testClass = UserDaoTest, testInstance = com.example.UserDaoTest@266da047, testMethod = testSelect@UserDaoTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@35b74c5c testClass = UserDaoTest, locations = '{}', classes = '{class com.example.DemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.mybatis.spring.boot.test.autoconfigure.MybatisTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@2e570ded key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@61001b64, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@26e356f0, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@272113c4, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@3f6f6701, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@9647a2c9, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@13e344d, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.jdbc.support.JdbcTransactionManager@73608eb0]; rollback [true]
2022-01-31 10:55:49.456 INFO 16468 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@3576ddc2 testClass = UserDaoTest, testInstance = com.example.UserDaoTest@266da047, testMethod = testSelect@UserDaoTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@35b74c5c testClass = UserDaoTest, locations = '{}', classes = '{class com.example.DemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.mybatis.spring.boot.test.autoconfigure.MybatisTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@2e570ded key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration, org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@61001b64, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@26e356f0, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@272113c4, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@3f6f6701, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@9647a2c9, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@13e344d, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]
2022-01-31 10:55:49.468 INFO 16468 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-01-31 10:55:50.017 INFO 16468 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
参考
- https://www.testcontainers.org/
- https://b1a9idps.com/posts/test-containers/
- https://zenn.dev/kentama/articles/aa7bbe728845da
ご意見・ご指摘等あればコメントいただけると幸いです。