おはようこんにちはこんばんは。
Exposedを使った開発をしていてデータベーステストを実行したいときに、テスト関数を実行するごとにテーブルの中身を綺麗さっぱり消したいことがあります。
Laravelのようなフレームワークには RefreshDatabase
や DatabaseTransactions
のようなテスト実行時に入れたものをテストが終わったときに消してくれる仕組みがありますが、Exposedにはそのようなものは用意されてないので何らかの方法で消すしかありません。
毎回使ったテーブルの中身を消しに行くのはなかなか億劫なので、ベースになる抽象クラスを作っておいてそれを継承して使う形にして何もしなくても勝手に毎回中身が空になるテストを書いてみたので、そのメモです。
テストクラスのベースとなる抽象クラスでそれを実装してみる
今回はマイグレーションにflywayを使っているので、それのテーブルを除いて全てのテーブルを取得して中身を消すというものを書いてみました。
また、今回は kotlin.test
を使っている前提で書いているので通常のJUnitなどを使っている場合は適宜読み替えて書き変えてください。
abstract class BaseTest {
private fun setupApplication() {
// DBへの接続のセットアップなどの必要な初期化処理を行う
}
@BeforeTest
fun beforeBaseTest() {
setupApplication()
truncateDatabase()
}
private fun truncateDatabase() {
transaction {
// 外部キー制約があるテーブルをTRUNCATEするために一時的に制約を取る
TransactionManager.current().exec("SET FOREIGN_KEY_CHECKS = 0")
// flywayのテーブルを除いて全てのテーブルをTRUNCATEする
db.dialect.allTablesNames().filterNot { it.contains("flyway_schema_history") }.forEach {
TransactionManager.current().exec("TRUNCATE TABLE $it")
}
// 一時的に外していた制約を戻す
TransactionManager.current().exec("SET FOREIGN_KEY_CHECKS = 1")
}
}
}
思ったより簡単ですね!
また、TRUNCATE
時には外部キー制約周りの罠に引っかかることもあるので、(中身全部消しちゃうし良いでしょうということで) 一旦外部キー制約のチェックを強制的に外してTRUNCATE TABLE
を実行してます。
テストを実行してみる
テストケースごとにしっかりテーブルの中身がTRUNCATEされてますね!
さいごに
普段業務や趣味でLaravelやRailsを触っていると、あれ?これも無いのぉ!?とびっくりすることもありますが、案外頑張れば意外と簡単に実装出来るのでExposedとKtorを使った開発もアリだなあと思いました。