LoginSignup
2
2

More than 1 year has passed since last update.

Laravel(PHP8) RefreshDatabaseが使えない!?

Last updated at Posted at 2023-01-26

概要

RefreshDatabaseをPHP8系で利用するとエラーになり、ユニットテストができないようです。
対処方法はいくつか考えられますが、おすすめの2パターンを紹介します。
プロジェクトやテスト内容に応じて、お好きな方をお使いいただければと思います。
もし、この方法がいいよ、などあればコメントにて教えてください。

環境

  • PHP 8.0.9
  • Laravel Framework 8.83.27
  • PHPUnit 9.5.28

RefreshDatabaseを使うと遭遇するエラー

RefreshDatabaseを使うと以下のエラーに遭遇します。

PDOException: There is no active transaction

/var/www/vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:279
/var/www/vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:254
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/RefreshDatabase.php:105
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:246
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:158

このエラーについては、[8.x] Fix error PDOException: There is no active transaction でも議論されているようです。

解決策

1. TraitをRefreshDatabaseからDatabaseMigrationsに変える

変更内容

コード
namespace Tests\Unit;

- use Illuminate\Foundation\Testing\RefreshDatabase;
+ use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;

class SampleTest extends TestCase
{
-     use RefreshDatabase;
+     use DatabaseMigrations;

エラーは出なくなりますが、DatabaseMigrationsはmigrate:freshを都度行います。
migrate:freshコマンドは、データベースからすべてのテーブルを削除したあと、migrateコマンドを実行します。そのため、処理に時間がかかります。

実行結果

./vendor/bin/phpunit tests/Unit/SampleTest.php
PHPUnit 9.5.28 by Sebastian Bergmann and contributors.

......                                                              6 / 6 (100%)

Time: 00:36.298, Memory: 22.55 MB

OK (6 tests, 6 assertions)

2. setUp()migratetruncateを行う

変更内容

ユニットテスト内でsetUp()をオーバーライドして、migrateの実行とテストに必要なテーブルのtruncateを行います。

namespace Tests\Unit;

use App\Models\Sample;
use Tests\TestCase;

class SampleTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        $this->artisan('migrate');
        Sample::truncate();
    }

migrateは未処理のマイグレーションのみ実行します。
テーブルの初期化をする必要がある場合は対象となるテーブルのみtruncateしましょう。

※ 処理済みのマイグレーションファイルを編集など行なった場合にもマイグレーションの再実行はされないので注意が必要です。

実行結果

./vendor/bin/phpunit tests/Unit/SampleTest.php
PHPUnit 9.5.28 by Sebastian Bergmann and contributors.

......                                                              6 / 6 (100%)

Time: 00:12.223, Memory: 22.55 MB

OK (6 tests, 6 assertions)

1.のDatabaseMigrationsを利用した場合と比較すると約3倍早いですね。。。

まとめ

個人的には、開発初期段階や比較的小さいプロジェクトであればDatabaseMigrationsを利用する方法で良いと思います。しかし、中規模以上のプロジェクトでマイグレーションするテーブルやファイルが多い場合、ユニットテストに時間がかかり過ぎてしまいかなり非効率です。この辺りはプロジェクトに応じてご検討いただければと思います。

参考文献

2
2
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
2
2