LoginSignup
5
2

More than 5 years have passed since last update.

【Laravel5.7】テスト時にHTTPレスポンスからlaravel_sessionが取れず死んだ

Posted at

laravel_sessionが取れない

Laravelでは、特に設定変更しなければlaravel_sessionというCookie1が発行され、それを使ってセッションを管理します。

テストからlaravel_sessionをチェックしたかったのだけれども、できなかったのでその記録をメモ。
なお解決はしていない。

class FooTest extends TestCase{
    /**
     * なんかリクエストするテスト
     * @return void
     */
    public function testFoobar(){
        $response = $this->get('foo/bar');
        $response->assertStatus(200)->assertCookieNotExpired('laravel_session');
    }
}

なにひとつ失敗する要素がない。

1) Tests\Feature\FooTest::testFoobar
Cookie [laravel_session] not present on response.
Failed asserting that null is not null.

FAILURES!
Tests: 1, Assertions: 2, Failures: 1.

はい。

リクエストは成功しレスポンスコード200が返ってきている。
getContent()でレスポンス本体が取得できるが、それも想定通りの内容で、別のAPIをリクエストしていたということもない。

    var_dump($response->headers->getCookies());
array(0) {}

何も取得できていない。
どういうことなの。

なんか別のCookie出してみる

コントローラ

class FooController extends Controller{
    public function barAction(Request $request){
        return response()->cookie('hoge', 'fuga', -1);
    }
}

ブラウザから確認。

Set-Cookie: hoge=xxx; expires=xxx; Max-Age=0; path=/; httponly
Set-Cookie: laravel_session=xxx; expires=xxx; Max-Age=7200; path=/; httponly

中身は暗号化されているため値が正しいかはわからないが、Cookie自体はきちんと発行されている。

テスト。

class FooTest extends TestCase{
    public function testFoobar(){
        $response = $this->get('foo/bar');
        var_dump($response->headers->getCookies());
    }
}

実行結果。

array(1) {
  [0]=>
  object(Symfony\Component\HttpFoundation\Cookie)#396 (10) {
    ["name":protected]=>
    string(4) "hoge"
    ["value":protected]=>
    string(192) "xxx"
    ["domain":protected]=>
    NULL
    ["expire":protected]=>
    int(9999999999)
    ["path":protected]=>
    string(1) "/"
    ["secure":protected]=>
    bool(false)
    ["httpOnly":protected]=>
    bool(true)
    ["raw":"Symfony\Component\HttpFoundation\Cookie":private]=>
    bool(false)
    ["sameSite":"Symfony\Component\HttpFoundation\Cookie":private]=>
    NULL
    ["secureDefault":"Symfony\Component\HttpFoundation\Cookie":private]=>
    bool(false)
  }
}

追加で出力したhogeだけが取得できた。

つまり、laravel_sessionは自動的に隠蔽されるということなのか?

でもセッションは継続してる

テストを1項目追加。

class FooTest extends TestCase
{
    /**
     * テストを追加
     * @return void
     */
    public function testFoobar(){
        $response = $this->get('foo/bar');

        // foo/barが前提のリクエスト
        $response2 = $this->get('foo/baz');
        $response2->assertStatus(200);
    }
}

コントローラ。

class FooController extends Controller{

    public function barAction(Request $request){
        $request->session()->put('hoge', 'fuga');
    }

    public function bazAction(Request $request){
        if($request->session()->get('hoge') === 'fuga'){
            return [];
        }
        abort(404);
    }
}

foo/bazに来たときに、foo/barを経由していれば200、していなければ404が出力されることになる。
さて結果は?

OK (1 test, 1 assertion)

はい。

なぜなのか。

セッションデータは何処にあるの?

ここ。

class FooTest extends TestCase
{
    public function testFoobar(){
        $response = $this->get('foo/bar');
        $response2 = $this->get('foo/baz');

        // セッションデータはここ
        var_dump($this->app['session']->all());
    }
}

セッションIDではなく、["hoge"]=>"fuga"というデータそのものがここに入ってる。

laravel_sessionはどこにあるの?

どこでしょうね?

どうにかした

laravel_sessionではなく別のCookieを発行して、そちらに対してassertCookieXXXを行うことでお茶を濁した。

なお、"Cookieが発行されていること"そのものを見る必要がなく、セッションの中身だけ検証すればよいのであれば、最初からassertSessionXXXを使うといい。

感想

結局laravel_sessionが何処で消されているのかはわからなかった。

$response = $kernel->handle(
    $request = Request::createFromBase($symfonyRequest)
);

とかのあたりね、そのね、全く意味がわからんのじゃけど。


  1. 実際はstrtolower(env('APP_NAME')).'_session'のような名前になる 

5
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2