Функциональный тест Symfony2 Недоступное поле "токен"


Я создаю функциональный тест в Symfony, используя пакет функциональных тестов Liip.

В настоящее время я застрял на отправке формы.
Я пытаюсь добавить новый "журнал", используя функциональный тест.

Если я попытаюсь добавить новый журнал через пользовательский интерфейс, я получу следующие параметры запроса:

'WorkLog' => array(
    'submit' => '',
    'hours' => '8',
    'minutes' => '0',
    'note' => 'some text',
    '_token' => '4l5oPcdCRzxDKKlJt_RG-B1342X52o0C187ZLLVWre4' 
);

Но когда тест отправляет форму, я получаю те же параметры, но без токена

 'WorkLog' => array(
    'submit' => '',
    'hours' => '8',
    'minutes' => '0',
    'note' => 'some text'
);

Я подумал, что смогу решить проблему, добавив поле _token на запрос формы, но когда я снова запустил тест, он выдал мне ошибку:

Исключение InvalidArgumentException: Недоступное поле "_token"

Код функционального теста:

namespace App\AdminBundle\Tests\Controller;

use Liip\FunctionalTestBundle\Test\WebTestCase;

use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\BrowserKit\Cookie;

class LogControllerTest extends WebTestCase
{
    private $client;
    private $em;
    private $fixtures;

    public function setUp()
    {
        $this->client = static::makeClient();
        $this->em = $this->client->getContainer()->get('doctrine')->getManager();

        $this->fixtures = $this->loadFixtures(array(
            'App\AdminBundle\DataFixtures\ORM\LoadUserData',
            'App\AdminBundle\DataFixtures\ORM\LoadSubscriptionTypesData',
            'App\AdminBundle\DataFixtures\ORM\LoadSubscriptionData',
            'App\AdminBundle\DataFixtures\ORM\LoadWorkLogData',
        ))->getReferenceRepository();
    }

    public function testAddNewLog()
    {
        $accountId = $this->fixtures->getReference('userAccount')->getId();

        // log in with admin account
        $this->logIn('adminAccount');

        $crawler = $this->client->request('GET', '/admin/worklog/account/'.$accountId.'/add');
        $csrfToken = $this->client->getContainer()->get('form.csrf_provider')->generateCsrfToken('post_type');

        $form = $crawler->selectButton('WorkLog_submit')->form(array(
            'WorkLog' => array(
                'hours' => '8',
                'minutes' => '0',
                'note' => 'some text',
                '_token' => $csrfToken
            ),
        ), 'POST');

        $crawler = $this->client->submit($form);
    }
}

Мой вопрос: Как я могу отправить форму с токеном?

Author: jack, 2015-11-20

2 answers

Я не работаю с пакетом функциональных тестов Liip, но обычно я работаю с формой и _token следующим образом:

    $crawler = $this->client->request('GET', $url);

    // retrieves the form token
    $token = $crawler->filter('[name="select_customer[_token]"]')->attr("value");

    // makes the POST request
    $crawler = $this->client->request('POST', $url, array(
        'select_customer' => array(
            '_token' => $token,
            'customerId' => $customerId,
        ),
    ));

Надеюсь, это поможет.

 3
Author: Matteo, 2017-09-08 21:34:10

Я столкнулся с очень похожей проблемой в течение нескольких часов... Мой метод был немного другим. Когда я просил о помощи, Stackoverflow обнаружил возможный дубликат, и я нашел ваш вопрос. Ваш вопрос поможет мне ответить на наши схожие проблемы.

Ты делаешь это:

    $form = $crawler->selectButton('WorkLog_submit')->form(array(
        'WorkLog' => array(
            'hours' => '8',
            'minutes' => '0',
            'note' => 'some text',
            '_token' => $csrfToken
        ),
    ), 'POST');

Вы пытались сделать это за один шаг. Но это невозможно, потому что функциональный пакет Liip пытается установить массив массива с помощью какого-то волшебного метода, и он выходит из строя. Я понял, что мы должны сделать это с большим количеством шагов:

Я использую его в своем коде так (вы можете видеть, что я больше не использую пакет Liip):

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class GameControllerTest extends WebTestCase
{
    public function testLoadGame(){


        $client = static::createClient();
        $crawler = $client->request('GET', '/loadGame');
        $form = $crawler->selectButton('Load')->form();
        $field = $form->get("load[uuid]");
        $field->setValue($uuid1[0]);
        $form->set($field);
        $client->submit($form);
        $response = $client->getResponse();
        self::assertTrue($response->isRedirect('/game'));

    }
}

Поэтому я думаю, что решение вашей проблемы заключается в следующем:

    $form = $crawler->selectButton('WorkLog_submit')->form();        
    //dump($form) //uncomment this line to have a look on the array of array
    $fieldToken = $form->get("WorkLog[_token]");
    $fieldToken->setValue($csrfToken);
    $form->set($fieldToken);
    $client->submit($form);
 0
Author: Alexandre T, 2016-12-13 21:51:27