Symfony2 で作成したコントローラーの PHP で小さなテストを行いました。
class DepositControllerTest extends WebTestCase {
public function testDepositSucceeds() {
$this->crawler = self::$client->request(
'POST',
'/deposit',
array( "amount" => 23),
array(),
array()
);
$this->assertEquals(
"Deposit Confirmation",
$this->crawler->filter("title")->text());
}
}
ここまでは、すべてが素晴らしかったです。ページの更新中に再送信の可能性を無効にしたいことに気付いたときに問題が発生しました。そこで、送信ごとにノンスを送信する小さなメカニズムを追加しました。
次のように機能します。
class ReplayManager {
public function getNonce() {
$uid = $this->getRandomUID();
$this->session->set("nonce", $uid);
return $uid;
}
public function checkNonce($cnonce) {
$nonce = $this->session->get("nonce");
if ($cnonce !== $nonce)
return false;
$this->session->set("nonce", null);
return true;
}
}
そのため、フォームを表示するときにノンスを取得し、送信するときにそれを消費するようにコントローラーを変更する必要がありました。
しかし今、これは問題を引き起こします。POST /deposit
どのナンスを送信すればよいかわからないため、リクエストを送信できません。GET /deposit
最初にフォームをレンダリングするように要求し、フォームを設定して で使用することを考えましたPOST
が、Symfony2 セッションが PHPUnit で動作していないと思われます。
どうすればこの問題を解決できますか? Selenium テストには行きたくありません。かなり遅いので、たくさんのテストを書き直さなければならないことは言うまでもありません。
更新:リクエストに応じて、コントローラー コードの非常に単純化されたバージョンを追加します。
class DepositController extends Controller{
public function formAction(Request $request){
$this->replayManager = $this->getReplayManager();
$context["nonce"] = $this->replayManager->getNonce();
return $this->renderTemplate("form.twig", $context);
}
protected function depositAction(){
$this->replayManager = $this->getReplayManager();
$nonce = $_POST["nonce"];
if (!$this->replayManager->checkNonce($nonce))
return $this->renderErrorTemplate("Nonce expired!");
deposit($_POST["amount"]);
return $this->renderTemplate('confirmation.twig');
}
protected function getSession() {
$session = $this->get('session');
$session->start();
return $session;
}
protected function getReplayManager() {
return new ReplayManager($this->getSession());
}
}