LoginSignup
10
7

More than 3 years have passed since last update.

Laravelのテストでrollbackされない問題

Posted at

LaravelのPHPUnitの拡張機能にIlluminate\Foundation\Testing\DatabaseTransactionsトレイトというものがあります。
これはsetUpでbeginTransactionし、tearDownでrollbackすることでテスト毎にデータを捨ててクリーンにデータベースを保ちながらテストコードを書くことができる機能です。(大げさ)

この機能を利用しているのでsetUpでSeederを利用してテストデータを挿入していたので後続のテストには影響がない前提でテストを書いていたにもかかわらずrollbackされなくて後続のテストに影響が出てしまったケースがありました。
そのコードが以下

use DatabaseTransactions;

protected function setUp(): void
{
    parent::setUp();
    \DB::table('クリアにしたいテーブル')->truncate();
    $this-seed('テストケースデータ');
}

setUp内で特定のテーブルに対してtruncateを実行しています。
これには以下の背景がありました。

  • MySQLではrollbackしてもautoincrementのカウンタは戻らない
  • 特定のautoincrementの値であることを検証したい(そんなテストもどうかと思うというツッコミは控えてほしい)

なので、truncateでもともと入ってるデータはきれいにしてしまえ、という思案です。
ですが先述の通りこのコードには問題があります。

それは、MySQLはtransaction中にtruncateを実行すると暗黙的にcommitするということです。
ということでtruncateコード後のseedは無事コミットされているという具合ですね。

こういうケースではIlluminate\Foundation\Testing\RefreshDatabaseトレイトを利用することでDBを空っぽにしてくれます。

まとめ

  • MySQLはtransaction中にtruncateを実行すると暗黙的にcommitする
  • Illuminate\Foundation\Testing\RefreshDatabaseを使おう
10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7