🎻

[Symfony] 機能テストでCSRFトークンを送る方法

2020/12/18に公開

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());

delete11 は削除対象のID)という文字列をキーにトークンを生成して、その値をリクエストに乗せるだけです。

以上、どこかの誰かのお役に立てば幸いです!

Symfony Advent Calendar 2020、明日も僕です!笑 お楽しみに!

GitHubで編集を提案

Discussion