🕵🏻

LaravelでPHPUnitテスト実行前のキャッシュクリアを自動で実行されるようにする

2022/11/24に公開2

はじめに

※開発用データベースとテスト用のデータベースを分けて用意している場合のみに向けた記事となります

Laravelでテスト実行時にCacheがあると、phpunit.xmlで設定している環境変数よりもCacheが優先されてしまう。

優先度はbootstrap/cache/config.php > phpunit.xml > .env となる

Cacheが読まれてしまうとテスト実行時に開発用のDBが吹っ飛んでしまう。
手動でphp artisan config:clear とするのも忘れる可能性があり、心理的にも良くないので、
良い解決法がないか探したところ、LaravelのGitHubリポジトリのissueで見つけたので、紹介します。

issueのリンク

環境

  • Windows11(WSL2)
  • PHP 7.4.x
  • Composer 2.x
  • Laravel 8.75.x
  • phpunit 9.5.10

やったこと

tests/TestCase.php

TestCase.phpのコードを見てみます。

tests/TestCase.php
<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
}

CreatesApplicationトレイトがクラスに追加されているので、追ってみます。

tests/CreatesApplication.php
<?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()をオーバーライドして、キャッシュをクリアする処理を入れます。

以下コードの通りになります。

test/TestCase.php
<?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