Closed1

PHP8.3に更新後に`@runInSeparateProcess`を設定しているテストが落ちる様になった為調査する

たぬきたぬき

暫く触れていなかったリポジトリのバージョンを諸々更新してPHP8.2からPHP8.3へと更新。

下記のバージョンの状態でphpunitを実行してみたところ、staticメソッドのテスト関連で@runInSeparateProcessのアノテーションを設定しているテストが落ちる様になっていたので備忘録的なメモを記載。

*こちらこちらの記事などを見るに、Laravel11にアップグレードすれば解消出来る想定。
事情があってアップグレード出来ない人向け。

名前 バージョン
PHP 8.3.11
Laravel 10.48.25
PHPUnit 10.5.40

テスト対象のクラスの例

staticメソッドtestTargetMethod内でMockTargetClass1クラスのtestMethodを呼び出して値を返すメソッド。(本来は他にも少し処理を入れています。)

class TestTargetClass1
{
    /**
     * target method.
     *
     * @param string $value
     * @return string
     */
    public static function testTargetMethod(
        string $value
    ): string {
        return MockTargetClass1::testMethod($value);
    }
}

テストコードの例

TestTargetClass1クラスのtestTargetMethodのテストコード。
内部で呼び出しているMockTargetClass1::testMethodをmockしている。

更新前まで正常終了していた下記のテストが更新後にエラーが発生する様になっていた。

namespace Tests\Unit\Path;

use App\Path\TestTargetClass1;
use App\Path\MockTargetClass1;
use Tests\TestCase;
use Mockery;

class MockeryTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();
    }

    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }

    /**
     * data privider for testTargetClass.
     * @return array
     */
    public static function targetClassDataProvider(): array
    {
        return [
            'parameter' => [
                'testParam' => 'testValue',
                'expect' => 'MockValue',
            ],
        ];
    }

    /**
     * test.
     *
     * @dataProvider targetClassDataProvider
     * @runInSeparateProcess
     * @preserveGlobalState disabled
     * @param string $testParam
     * @param string $expect
     * @return void
     */
    public function testTargetClass(
        string $testParam,
        string $expect
    ): void {
        // MockTargetClass1をモック化
        $mock = (new Mockery())->mock('overload:'.MockTargetClass1::class);
        $mock->shouldReceive('testMethod')->once()->andReturn('MockValue');

        $this->assertEquals(TestTargetClass1::testTargetMethod($testParam), $expect);
    }
}

解決方法

こちらのコメントを見るに、Laravel側の影響によるもの。
その為、応急処置として継承元のTestCaseクラスをPHPUnit\Framework内のクラスに変更する。

- use Tests\TestCase;
+ use PHPUnit\Framework\TestCase;

これによりエラーが解消される。

継承元を変更した事でFacadeなどLaravel関連のメソッドを利用出来なくなっている為、必要に応じてそれらのメソッドをmockを掛ける。

*phpunitのバージョン12以降でアノテーションは利用出来なくなる為、phpdocの書き方自体も変更した方が良い。
参考

このスクラップは2025/01/12にクローズされました