Closed4
SymfonyのWebTestCaseでリクエスト前にセッションに任意の値をセットしておく方法
これをつぶやいて
すぐにこれを思いついたけど
しけちゃん先生が他に2つもアイデアをくれた(神)
最初に思いついた方法
// 一旦、適当なページをリクエスト
$client->request('GET', '/');
// リクエスト先がもしリダイレクトレスポンスを返しても動作するように
while ($client->getResponse() instanceof RedirectResponse) {
$client->followRedirect();
}
// リクエストからセッションを取得
$session = $client->getRequest()->getSession();
// セッションに任意のデータをセット
$session->set('任意のキー', '任意の値');
$client->request('GET', '/someActionUsesSessionData');
self::assertThat('何かを検査');
これで一応動くけど、絶妙にダサい
SessionFactoryをモック
しけちゃんの提案をヒントに、SessionFactory をモックして手動でセットしたセッションデータが保持されるようにしてみた
<?php
// tests/Fake/FakeSessionFactory.php
declare(strict_types=1);
namespace App\Tests\Fake;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
use Symfony\Component\HttpFoundation\Session\SessionFactoryInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
#[AsDecorator(decorates: 'session.factory')]
final class FakeSessionFactory implements SessionFactoryInterface
{
public function __construct(
#[AutowireDecorated]
private readonly SessionFactoryInterface $decorated,
private ?SessionInterface $session = null,
) {
}
public function createSession(): SessionInterface
{
return $this->session ??= $this->decorated->createSession();
}
}
// リブートが有効だとリクエストごとにモックが取り消されてしまうのでこれが必要
$client->disableReboot();
// セッションを手動で開始
$session = $client->getContainer()->get('session.factory')->createSession();
// セッションに任意のデータをセット
$session->set('任意のキー', '任意の値');
$client->request('GET', '/someActionUsesSessionData');
self::assertThat('何かを検査');
スッキリ!
SessionFactory の実装を見れば分かるように、
createSession()
が呼ばれる度に新しいSession
インスタンスが生成されるので、モックせずに本物のsession.factory
のcreateSession()
を手動で呼んでセッションデータをセットしても、次にリクエスト実行時にcreateSession()
されるときにはまた新しいSession
インスタンスが生成されるのでダメです
セッションCookieを自作してクライアントにセット
こちらは SessionFactory
をモックする必要なし
// セッションに任意のデータをセットした上で、セッションCookieを作成してクライアントにセット
$session = $client->getContainer()->get('session.factory')->createSession();
$session->set('任意のキー', '任意の値');
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$client->getCookieJar()->set($cookie);
$client->request('GET', '/someActionUsesSessionData');
self::assertThat('何かを検査');
SessionFactory
をモックする方法と違って $client->disableReboot()
が必要なく、副作用が少ないので個人的にはこの方法が一番しっくり来た
参考
このスクラップは5ヶ月前にクローズされました