はじめに
Symfony2でテストを書いたことを前提に話を進めます。
XMLHttpRequestなリクエストって
ブラウザからAjaxで呼ばれるAPIを作ったときに、Controllerのテスト書くと思います。
その際、$request->isXmlHttpRequest()
かどうかチェックしているとすると、テスト的にも、それを区別する必要があります。
XMLHttpRequestかどうかは、リクエストヘッダのX-Requested-With
がXMLHttpRequest
かどうかによって判断しているようです。
public function isXmlHttpRequest()
{
return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
}
request関数の引数に$headersが見当たらない?
下記のようなテストコードだったとして、$client->request
でリクエストヘッダが指定できれば、解決しそうです。
<?php
namespace App\Test\Controller;
use Symfony\Component\HttpKernel\Client;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
// Silexの場合は、use Silex\WebTestCase;
class ApiControllerTest extends WebTestCase
{
/**
* @test
*/
public function apiAction()
{
$client = self::createClient();
/** @var Client $client */
$client->request('GET', '/path/to/api');
$this->assertTrue($client->getResponse()->isOk());
$this->assertJson($client->getResponse()->getContent());
}
が、しかし、HTTPクライアントのrequest関数の引数に$headersが見当たらないのです。
/**
* Calls a URI.
*
* @param string $method The request method
* @param string $uri The URI to fetch
* @param array $parameters The Request parameters
* @param array $files The files
* @param array $server The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does)
* @param string $content The raw body data
* @param bool $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload())
*
* @return Crawler
*
* @api
*/
public function request($method, $uri, array $parameters = array(), array $files = array(), array $server = array(), $content = null, $changeHistory = true)
ググると、下記のissueが見つかり、ますます不安になります。
[BrowserKit]Cannot set Custom Header · Issue #5074 · symfony/symfony
結論、サーバー変数'HTTP_X_REQUESTED_WITH'に'XMLHttpRequest'をセットする
ここで慌てずに、request関数のコメントをよく見ると、
@param array $server The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does)
とありますので、試しにサーバー変数'HTTP_X_REQUESTED_WITH'に'XMLHttpRequest'を指定すると、期待どおり動作します。
$client->request('GET', $apiUrl, [], [],
['HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']);
$this->assertTrue($client->getResponse()->isOk());
$this->assertJson($client->getResponse()->getContent());
}
おわりに
毎回、サーバー変数セットするのもあれなんで、Clientクラスを拡張して、ajaxRequest関数を作ってもいいかもしれません。
参考になりましたら、幸いです。