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

# laravel_sessionが取れない

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

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


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

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

```bash
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をリクエストしていたということもない。

```php
    var_dump($response->headers->getCookies());
```

```bash
array(0) {}
```

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

# なんか別のCookie出してみる

コントローラ

```php
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自体はきちんと発行されている。

テスト。

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

実行結果。

```php
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項目追加。

```php
class FooTest extends TestCase
{
    /**
     * テストを追加
     * @return void
     */
    public function testFoobar(){
        $response = $this->get('foo/bar');
        
        // foo/barが前提のリクエスト
        $response2 = $this->get('foo/baz');
        $response2->assertStatus(200);
    }
}
```

コントローラ。

```php
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)
```

はい。

なぜなのか。


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

ここ。

```php
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`が何処で消されているのかはわからなかった。

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

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



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