COil
COil

Reputation: 7596

Symfony: changing the request base class and updating the test environment

I have modified the base Request class of my application as explained in the accepted answer of this question. It works very well, except when launching my functional tests, I get the following error:

Controller "My\Bundle\AppBundle\Controller\MyController::searchAction()" requires that you provide a value for the "$request" argument (because there is no default value or because there is a non-optional argument after this one). (500 Internal Server Error)

Indeed there is no app_test.php controller used. I was hoping it could be done in the createCient() function of my WebTestCase base class, but how?

/**
 * Creates a Client.
 *
 * @param array $options An array of options to pass to the createKernel class
 * @param array $server  An array of server parameters
 *
 * @return Client A Client instance
 */
protected static function createClient(array $options = array(), array $server = array())
{
    static::bootKernel($options);

    $client = static::$kernel->getContainer()->get('test.client');
    $client->setServerParameters($server);

    return $client;
} 

[Edit 21 September 2017]:

I have to do the following when migrating to Symfony 3.3:

config_test.yml:

parameters:
    test.client.class: My\Bundle\AppBundle\Tests\Client

services:
    test.client:
        class: '%test.client.class%'
        arguments: ['@kernel', '%test.client.parameters%', '@test.client.history', '@test.client.cookiejar']

Upvotes: 2

Views: 1131

Answers (1)

Aleksander Wons
Aleksander Wons

Reputation: 3967

I think you have to override the class for test.client which, by default, uses Symfony\Bundle\FrameworkBundle\Client.

Something like:

<parameters>
    <parameter name="test.client.class">My\Bundle\AppBundle\Test\Client</parameter>
</parameters>

First, take a look at the base class Symfony\Component\BrowserKit\Client.

If you look at the request method of this class you will find this:

public function request(/* ... */)
{
    // ...
    $this->internalRequest = new Request($uri, $method, $parameters, $files, $this->cookieJar->allValues($uri), $server, $content);

    $this->request = $this->filterRequest($this->internalRequest);
    // ...
}

Now look at the Symfony\Component\HttpKernel\Client and the filterRequest method:

protected function filterRequest(DomRequest $request)
{
     $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent());

    // ...
}

Here is where the actual magic happens. This is the method you have to override if you need to have a different request object.

Edit:

This $httpRequest is then going to be serialized and unserialized. Just take a look at the getScript method of Symfony\Component\HttpKernel\Client class.

Upvotes: 4

Related Questions