はじめに
Spring Boot でUnitテストを書いていた際に、executionPhase を使ってハマったことを残します。
バージョン
Spring Boot 3.4.2
ハマったこと
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_CLASS)
を付けたらトランザクションがコミットされることに気づかなかった。
経緯
クラスに@Sql
を書けば1回だけデータ投入され、各UTケース(メソッド)で利用できるかな、と思っていました。
動かしてみると、各ケースごとに@Sql
のデータ投入が動いていることに気づきました。
org.springframework.jdbc.datasource.init
のログレベルをDEBUGにして実行結果を確認。
logging:
level:
'[org.springframework.jdbc.datasource.init]': DEBUG
@SpringBootTest
@Transactional
@Sql
public class DemoTest {
@Test
void test1() {
System.out.println("test1");
}
@Test
void test2() {
System.out.println("test2");
}
}
2回、@Sql
のSQL(DemoTest.sql)が実行されています。
2025-02-02T12:50:30.509+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : Executing SQL script from class path resource [com/example/demo/DemoTest.sql]
2025-02-02T12:50:30.540+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : 0 returned as update count for SQL: CREATE TABLE IF NOT EXISTS m_class ( id INT auto_increment PRIMARY KEY, name VARCHAR(50) )
2025-02-02T12:50:30.549+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : 1 returned as update count for SQL: INSERT INTO m_class(name) VALUES('DemoTest')
2025-02-02T12:50:30.551+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : Executed SQL script from class path resource [com/example/demo/DemoTest.sql] in 40 ms.
~~ 中略 ~~
2025-02-02T12:50:31.354+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : Executing SQL script from class path resource [com/example/demo/DemoTest.sql]
2025-02-02T12:50:31.354+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : 0 returned as update count for SQL: CREATE TABLE IF NOT EXISTS m_class ( id INT auto_increment PRIMARY KEY, name VARCHAR(50) )
2025-02-02T12:50:31.355+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : 1 returned as update count for SQL: INSERT INTO m_class(name) VALUES('DemoTest')
2025-02-02T12:50:31.355+09:00 DEBUG 3664 --- [spring-boot-ut] [ main] o.s.jdbc.datasource.init.ScriptUtils : Executed SQL script from class path resource [com/example/demo/DemoTest.sql] in 1 ms.
どうせなら1回だけいいかな?と思い、以下を発見。付与してみたら1回だけに変わりました。
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_CLASS)
が!トランザクションがコミットされるようになってしまいました。
org.springframework.jdbc.support.JdbcTransactionManager
のログレベルをDEBUGにして確認。
logging:
level:
'[org.springframework.jdbc.datasource.init]': DEBUG
'[org.springframework.jdbc.support.JdbcTransactionManager]': DEBUG
2025-02-02T13:01:33.027+09:00 DEBUG 16396 --- [spring-boot-ut] [ main] o.s.jdbc.support.JdbcTransactionManager : Initiating transaction commit
UTが複数クラスあると、1個目のUTクラスの@Sql
のデータが残り、2個目のUTクラスの実行時に意図しない動きをしてしまいました。
加えてUTクラス単位でデータが繋がってしまうのはよくない。と。
結果
ExecutionPhase.BEFORE_TEST_CLASS
をやめて、ケース(メソッド)毎実行する方法に戻しました。
サンプルソース