Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

SymfonyでXMLHttpRequestなAPIをテストする方法

More than 3 years have passed since last update.

はじめに

Symfony2でテストを書いたことを前提に話を進めます。

XMLHttpRequestなリクエストって

ブラウザからAjaxで呼ばれるAPIを作ったときに、Controllerのテスト書くと思います。
その際、$request->isXmlHttpRequest()かどうかチェックしているとすると、テスト的にも、それを区別する必要があります。

XMLHttpRequestかどうかは、リクエストヘッダのX-Requested-WithXMLHttpRequestかどうかによって判断しているようです。

Symfony/Component/HttpFoundation/Request.php
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が見当たらないのです。

Symfony/Component/BrowserKit/Client.php
/**
 * 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関数を作ってもいいかもしれません。
参考になりましたら、幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away