もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

laravelでrouteにdomainを指定した場合のfeatureテスト方法

はじめに

こんばんは。

すごく短いですが、今日少し悩んだので、備忘録として残しておきます。

試した環境はこちら。

  • PHP 7.3.1
  • Laravel 5.8.28

laravelでmulti認証をやる際、routesにdomainが設定されている場合にどうやってfeatureテストを行うかを調査していたのですが、とりあえず以下みたいな感じで出来ました。

やってみた

こんな感じのroute設定があるとします。

routes.php

Route::group(['prefix' => 'api', 'domain' => config('app.admin_host')], function () {
    Route::post('/auth/login', 'AdminLoginController@login');
    Route::delete('/auth/logout', 'AdminLoginController@logout');
    Route::get('/auth/refresh', 'AdminLoginController@refresh');
});

Route::group(['prefix' => 'api', 'domain' => config('app.user_host')], function () {
    Route::post('/auth/login', 'UserLoginController@login');
    Route::delete('/auth/logout', 'UserLoginController@logout');
    Route::get('/auth/refresh', 'UserLoginController@refresh');
});

config('app.admin_host') とかは .envとかで指定して app.php で読み込んでおきます。

とりあえずこんな感じで登録しておきます。

.env

ADMIN_HOST=127.0.0.1
USER_HOST=localhost

config/app.php

return [
    ...
    'admin_host' => env('ADMIN_HOST', 'admin.kojirock'),
    'user_host'  => env('USER_HOST', 'user.kojirock'),
];

それぞれのrouteのfeatureテストを実行する際、ここで設定しているデータを取れる必要がありそうです。

なので、 phpunit環境変数を渡します。

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="MAIL_DRIVER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <env name="ADMIN_HOST" value="admin.local"/> ← これ
        <env name="USER_HOST" value="user.local"/>   ← これ
    </php>
</phpunit>

featureテストファイルには以下のようにテストコードを書きます。

AdminLoginControllerTest.php

<?php


namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

class AdminLoginControllerTest extends TestCase
{
    use DatabaseTransactions;

    public function testLogin()
    {
        $response = $this->post('http://admin.local/api/auth/login', [
            'email'    => 'kojirock5260@kojikoji.com',
            'password' => 'secret_secret_secret'
        ]);
        $data = json_decode($response->getContent(), true);
        $this->assertSame('xxxxxxxxxx', $data['accessToken']);
    }
}

これで問題なくテストが通りました。

終わりに

ぶっちゃけ、 config/app.php で設定する際の デフォルト設定でやってしまうというのもあるのですが、個人的に デフォルト設定にテストのものが適用する という運用が嫌なので今回はこのアプローチにしました。

dockerで作成したローカル環境でしか試してないので、circleCIとかで実行する際はまた勝手が違うかもしれません。

もっといいやり方あれば、ぜひ教えて下さい...

.env.testingに書けばいいよね?という一番スマートなやり方を教えてもらいました!

なるほどたしかにw

現場からは以上です。