Laravel のテストであるクラスのプロパティをテストから書き換えて初期化するには


この記事について

半分個人メモです。

ある特殊なテストを行いたくて、private なプロパティをテストメソッドから書き換えて実行する方法を探っていたところ、以下のやり方を思いついたので書き残しておきます。

はじめに

概要

あるクラスが config から読み取った値を private なプロパティにセットして初期化していて、その値を、あるテストメソッドでのみ、特殊な環境変数で上書きして実行したい、というケースに遭遇した際、リフレクションと無名クラスで対応できそうだったのでやってみました。

環境

  • PHP: 7.3.2
  • Laravel: 5.8.13
  • PHPUnit: 7.5.8

詳細

とあるクラス

<?php

namespace App\Services;

class SomeService
{
    private $config;

    public function __construct()
    {
        $this->config = config('services.some.config');
    }

    public function doSomething()
    {
        return $this->config;
    }
}

テストクラス

<?php

namespace Tests\Feature\Services;

use App\Services\SomeService;
use Tests\TestCase;

class SomeServiceTest extends TestCase
{
    public function testDoSomethingInGeneralEnvironment()
    {
        $service = app(SomeService::class);

        $this->assertEquals('hoge', $service->doSomething());
    }

    public function testDoSomethingInSpecialEnvironment()
    {
        $service = new class extends SomeService {
            public function __construct()
            {
                $class = new \ReflectionClass(SomeService::class);
                $property = $class->getProperty('config');
                $property->setAccessible(true);
                $property->setValue($this, env('SOME_SERVICE_CONFIG_OVERWRITTEN'));
            }
        };

        $this->assertEquals('fuga', $service->doSomething());
    }
}

config/services.php

    'some' => [
        'config' => env('SOME_SERVICE_CONFIG'),
    ],

.env

SOME_SERVICE_CONFIG=hoge
SOME_SERVICE_CONFIG_OVERWRITTEN=fuga

SOME_SERVICE_CONFIG_OVERWRITTEN は、.env.testing とか phpunit.xml とかに書いてもいいかもしれないです(テストでしか使わないやつなので)。