Symfony2:对ArrayCollection的测试给出了“无法访问的字段”

时间:2013-03-16 21:10:40

标签: symfony phpunit

在添加ArrayCollection成员的表单的功能测试中,有以下语句:

  

$ form ['client [members] [1] [fname]'] ='Benny';

使用DOM检查器验证字段名称。

此行的控制台输出是:

InvalidArgumentException: Unreachable field "members"

G:\Documents\workspace\sym\vendor\symfony\symfony\src\Symfony\Component\DomCrawler\Form.php:459
G:\Documents\workspace\sym\vendor\symfony\symfony\src\Symfony\Component\DomCrawler\Form.php:496
G:\Documents\workspace\sym\vendor\symfony\symfony\src\Symfony\Component\DomCrawler\Form.php:319
G:\Documents\workspace\sym\src\Mana\ClientBundle\Tests\Controller\ClientControllerTest.php:57

应该使用什么方法来测试添加ArrayCollection成员?

按要求编辑(n.b.,按照重定向开启):

    //link to trigger adding household member form
    $link = $crawler->selectLink('Add household member')->link();
    $crawler = $client->click($link);
    $form = $crawler->selectButton('Add client')->form();
    $form['client[members][1][fname]'] = 'Benny';
    $form['client[members][1][dob]'] = "3/12/1999";
    $crawler = $client->submit($form);
    $this->assertTrue($crawler->filter('html:contains("Client View Form")')->count() > 0);

3 个答案:

答案 0 :(得分:8)

我刚才遇到了同样的问题,经过一番研究后我找到了一个帮助我的解决方案。 A solution to remove a field from a Collection form type 这篇文章并不完全是你想要的,这个是删除元素而不是添加新元素。但原则是一样的。我做了什么,而不是$form->setValues() ... $form->getPhpValues(),我已经创建了一个数组,并发布了

在下面的示例中,表单的configurations字段为Collection

    $submitButton = $crawler->selectButton(self::BUTTON_ADD_APPLICATION);
    $form = $submitButton->form();
    $values = array(
        'Setup' => array(
            '_token' => $form['Setup[_token]']->getValue(),
            'name'   => 'My New Setup',
            'configurations' => array(
                0 => array(
                    'country' => 'HUN',
                    'value'   => '3',
                ),
                1 => array(
                    'country' => 'GBR',
                    'value'   => '0',
                ),
            ),
        ),
    );

    $client->request($form->getMethod(), $form->getUri(), $values);

希望它有所帮助!并感谢sstok的原始解决方案!

答案 1 :(得分:3)

这可以通过从submit()方法调用稍微修改过的代码来完成:

// Get the form.
$form = $crawler->filter('button')->form();

// Get the raw values.
$values = $form->getPhpValues();

// Add fields to the raw values.
$values['task']['tag'][0]['name'] = 'foo';
$values['task']['tag'][1]['name'] = 'bar';

// Submit the form with the existing and new values.
$crawler = $this->client->request($form->getMethod(), $form->getUri(), $values,
    $form->getPhpFiles());

// The 2 tags have been added to the collection.
$this->assertEquals(2, $crawler->filter('ul.tags > li')->count());

此示例中包含新闻值的数组对应于您拥有包含这些name的字段的表单:

<input type="…" name="FORM_NAME[COLLECTION_NAME][A_NUMBER][FIELD_NAME_1]" />
<input type="…" name="FORM_NAME[COLLECTION_NAME][A_NUMBER][FIELD_NAME_2]" />

使用此代码,表单中已存在现有字段(包括令牌),这意味着您无需添加所有字段。

字段的数量(索引)无关紧要,PHP将合并数组并提交数据,Symfony将在相应的字段中转换此数据。

您还可以从集合中删除元素:

// Get the values of the form.
$values = $form->getPhpValues();

// Remove the first tag.
unset($values['task']['tags'][0]);

// Submit the data.
$crawler = $client->request($form->getMethod(), $form->getUri(),
    $values, $form->getPhpFiles());

// The tag has been removed.
$this->assertEquals(0, $crawler->filter('ul.tags > li')->count());

来源:http://symfony.com/doc/current/book/testing.html#adding-and-removing-forms-to-a-collection

答案 2 :(得分:2)

如果使用javascript修改表单,则无法使用symfony测试框架对其进行测试。这样做的原因是symfony提供的DomCrawler只获取静态HTML并解析它,而不考虑浏览器使用图形用户界面(主要是javascript)进行的任何操作。

如果您需要测试一个javascript密集的项目,您需要使用一些框架,该框架使用浏览器的引擎(例如Selenium)或者可以解释javascript并执行DOM上的所有更改(例如Zombie.js)

一个很好的框架是Mink,它是测试框架和执行请求并解析结果的实际客户端之间的一个层。它提供了一个API,可以使用非常简单的PHP HTML Parser(类似于symfony使用的DomCrawler),Selenium,Zombie.js等等。