🎻
[Symfony] 機能テストでCSRFトークンを送る方法
Symfony Advent Calendar 2020 の18日目の記事です!🎄🌙小ネタですみません!
昨日は seihmd さんの DDDとORMのEntityを混同しないための考え方 でした✨
ちなみに、僕はよく TwitterにもSymfonyネタを呟いている ので、よろしければぜひ フォローしてやってください🕊🤲
やりたいこと
例えば、コントローラに以下のような delete()
アクションがあって、CSRFトークンのチェックをしているとしましょう。
bin/console make:crud
で自動生成される内容と同じなので一般的な実装だと思います。
/**
* @Route("/foo/{id}", name="foo_delete", methods={"DELETE"})
*/
public function delete(Request $request, Foo $foo)
{
if ($this->isCsrfTokenValid('delete'.$foo->getId(), $request->request->get('_token'))) {
$this->em->remove($foo);
$this->em->flush();
$this->addFlash('success', '削除しました。');
}
return $this->redirectToRoute('foo_index');
}
このアクションに対して機能テストを書きたい場合、
- 削除ボタンを設置している画面を一度開いて、フォームを送信することでCSRFトークンを含めた正常なリクエストを送る
- 手動でCSRFトークンを生成して、それを付加して削除アクションに直接リクエストを送る
の2つの方法が考えられます。
今回は後者のやり方を説明します。
やり方
と言ってもやることは本当に簡単で、サービスコンテナから security.csrf.token_manager
サービスを取得して使うだけです。
コントローラの実装が上記の例のようになっているとしたら、テストコードは以下のようになります。
$client = self::createClient();
$client->request('DELETE', '/foo/1', [
'_token' => $client->getContainer()->get('security.csrf.token_manager')->getToken('delete1')->getValue(),
]);
$client->request('GET', '/foo/1');
$this->assertEquals(404, $client->getResponse()->getStatusCode());
delete1
( 1
は削除対象のID)という文字列をキーにトークンを生成して、その値をリクエストに乗せるだけです。
以上、どこかの誰かのお役に立てば幸いです!
Symfony Advent Calendar 2020、明日も僕です!笑 お楽しみに!
Discussion