4
votes

I'm currently writing functionnal tests for my symfony app. I use symfony 3 (3.1.6) with phpunit 5.6.1. Edit : As requested by Alvin Bunk, my app is not a website, it is an API that returns only JSON. As i added in the two updates below, the Symfony test client sends a proper request object with the form data but the controller of the app receives an empty object.

Here is the code i use to test my form :

public function testSaveMediaFromMediaUrl()
{
    $client = static::createClient();
    $crawler = $client->request('GET', '/form');

    $form = $crawler->selectButton('OK')->form();
    $form['mediaUrl'] = 'http://example.com';

    $client->submit($form);
    var_dump($client->getResponse()->getContent());
}

The correct action of my controller is called but there is nothing in the request object when the action is called from the tests suite. using a regular web browser, everything works fine. In the controller, I use $request = Request::createFromGlobals(); to create the request object

I also tried this code to post the data and I get the same result : no POST data is received in the controller.

direct post request without using the form

public function testSaveMediaFromMediaUrl()
{
    $client = static::createClient();
    $crawler = $client->request('POST', '/media', ['mediaUrl' => 'http://example.com']);

    var_dump($crawler->html());
}

adding the data in the submit method

public function testSaveMediaFromMediaUrl()
{
    $client = static::createClient();
    $crawler = $client->request('GET', '/form');

    $form = $crawler->selectButton('OK')->form();

    $client->submit($form, ['mediaUrl' => 'http://example.com']);
    var_dump($client->getResponse()->getContent());
}

Is there something I'm doing wrong ?

EDIT:

Here is the dump of the request object I get in the controller action.

.object(Symfony\Component\HttpFoundation\Request)#1047 (21) {
  ["attributes"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#1050 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["request"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#1048 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["query"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#1049 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["server"]=>
  object(Symfony\Component\HttpFoundation\ServerBag)#1053 (1) {
    ["parameters":protected]=>
    array(35) {[...]}
  }
  ["files"]=>
  object(Symfony\Component\HttpFoundation\FileBag)#1052 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["cookies"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#1051 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }
  ["headers"]=>
  object(Symfony\Component\HttpFoundation\HeaderBag)#1054 (2) {
    ["headers":protected]=>
    array(0) {
    }
    ["cacheControl":protected]=>
    array(0) {
    }
  }
  ["content":protected]=>
  NULL
  ["languages":protected]=>
  NULL
  ["charsets":protected]=>
  NULL
  ["encodings":protected]=>
  NULL
  ["acceptableContentTypes":protected]=>
  NULL
  ["pathInfo":protected]=>
  NULL
  ["requestUri":protected]=>
  NULL
  ["baseUrl":protected]=>
  NULL
  ["basePath":protected]=>
  NULL
  ["method":protected]=>
  NULL
  ["format":protected]=>
  NULL
  ["session":protected]=>
  NULL
  ["locale":protected]=>
  NULL
  ["defaultLocale":protected]=>
  string(2) "en"
}

Edit-2:

Here is the dump of the request object sent by the client (in the test case : var_dump($client->getRequest()->request);) :

object(Symfony\Component\HttpFoundation\ParameterBag)#753 (1) {
  ["parameters":protected]=>
  array(4) {
    ["mediaUrl"]=>
    string(41) "http://example.com"
    ["url"]=>
    string(0) ""
    ["token"]=>
    string(0) ""
    ["sizes"]=>
    string(0) ""
  }
}

The "test browser" seems sends the form data to the app...

2
You should have mentioned in your post that it's a restful api and that you are expecting JSON to be returned. -1 for not showing that info in your post, and @Matteo gave a good answer (as usual) which you should upvote. If you update your post to include the api information, then I'll upvote it. - Alvin Bunk
That does not change nothing to my question... the problem is that the POST data seems to be lost between the request send by the test client and the handling into the app kernel : my controller receives an empty request object and it throws an error so nothing is returned neither HTML or JSON (just a 500 error) - ᴄʀᴏᴢᴇᴛ
I edited the post to add info aboit the app. the answer given by Matteo does not change anything to the problem... - ᴄʀᴏᴢᴇᴛ

2 Answers

4
votes

Problem solved :

In my controller, I used $request = Request::createFromGlobals() as written in the doc. I removed this line and added $request as a parameter of the controller action and now the request contains the POST data sent by the test client.

My action is now defined like this :

public function generateAction(Request $request) {
    // no more $request = Request::createFromGlobals();
    $request->request->get('mediaUrl'); // contains data
}
2
votes

usually a post request to a form return a redirect, if so check that the redirect is the correct response and follow the redirection, as example:

$client->submit($form);

$this->assertTrue($client->getResponse()->isRedirect());
$this->crawler = $client->followRedirect();

Hope this help

EDIT:

Another way could be:

$form = $crawler->selectButton('OK')->form(array(
    'mediaUrl' => 'http://example.com')
);

$client->submit($form);