LaravelでPHPUnitテスト実行前のキャッシュクリアを自動で実行されるようにする
はじめに
※開発用データベースとテスト用のデータベースを分けて用意している場合のみに向けた記事となります
Laravelでテスト実行時にCacheがあると、phpunit.xmlで設定している環境変数よりもCacheが優先されてしまう。
優先度はbootstrap/cache/config.php
> phpunit.xml
> .env
となる
Cacheが読まれてしまうとテスト実行時に開発用のDBが吹っ飛んでしまう。
手動でphp artisan config:clear
とするのも忘れる可能性があり、心理的にも良くないので、
良い解決法がないか探したところ、LaravelのGitHubリポジトリのissueで見つけたので、紹介します。
環境
- Windows11(WSL2)
- PHP 7.4.x
- Composer 2.x
- Laravel 8.75.x
- phpunit 9.5.10
やったこと
tests/TestCase.php
TestCase.phpのコードを見てみます。
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
}
CreatesApplicationトレイトがクラスに追加されているので、追ってみます。
<?php
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
trait CreatesApplication
{
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
return $app;
}
}
このcreateApplication()は全てのテストの継承元であるIlluminate\Foundation\Testing\TestCase
の
setUp()で実行されることが確認できます。
PHPUnitの公式ドキュメントを確認すると、
setUp()は各テストの前に実行されると記載されています。
そのため、createApplication()内でCacheをクリアするようにしてあげれば、手動で実行しなくてよくなります。
createApplication()をオーバーライド
tests/TestCase.php
でcreateApplication()をオーバーライドして、キャッシュをクリアする処理を入れます。
以下コードの通りになります。
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
$this->clearCache();
return $app;
}
protected function clearCache()
{
$command = 'optimize:clear';
\Illuminate\Support\Facades\Artisan::call($command);
}
}
これで仮にうっかり開発環境でキャッシュしてしまっている時に、テストを実行しても
実行前にキャッシュクリアするようになりました。
テスト実行後にThe /var/www/laravel/bootstrap/cache directory must be present and writable.が発生する
テスト実行後にThe /var/www/laravel/bootstrap/cache directory must be present and writable.
となるときは、
bootstrap/cacheに書き込み権限がないからです。
なので以下コマンドを入力してください。
$ chmod -R 777 bootstrap/cache
さいごに
makeコマンドを作成する方法など調べると色々やり方は出てきましたが、
今回紹介したやり方が個人的には一番しっくり来ました。
もっと良い方法があったり、不都合があるなどする場合はご教示いただければと思います。
Discussion
コマンド名からは想像付かないですが、optimize:clear
のコマンド1つで、上記のコマンド全て実行してくれます😃
参考: