Forms 使用symfony2和phpunit修改表单操作

Forms 使用symfony2和phpunit修改表单操作,forms,symfony,phpunit,Forms,Symfony,Phpunit,我目前正在使用Symfony2,并正在使用PHPUnit测试我的项目。 我想测试一个异常,当表单使用错误的参数提交或URL不完整时 我查阅了Symfony2和PHPUnit的文档,但没有找到任何类/方法 如何更改窗体操作的值?我想使用PHPUnit,这样创建的报告是最新的,我可以看到我代码的覆盖范围 编辑: 为了澄清我的问题,有一些新的内容。 如何在控制器中测试以“>”开头的行?(抛出$this->createNotFoundException('无法找到ParkingZone实体');) 当用

我目前正在使用Symfony2,并正在使用PHPUnit测试我的项目。 我想测试一个异常,当表单使用错误的参数提交或URL不完整时

我查阅了Symfony2和PHPUnit的文档,但没有找到任何类/方法

如何更改窗体操作的值?我想使用PHPUnit,这样创建的报告是最新的,我可以看到我代码的覆盖范围

编辑:

为了澄清我的问题,有一些新的内容。 如何在控制器中测试以“>”开头的行?(
抛出$this->createNotFoundException('无法找到ParkingZone实体');

当用户修改操作链接时,在控制器中,进程将通过异常(或错误消息,如果选择此操作)。我如何测试这个案例

控制器

查看:


{{form_标签(form.name,'name',{'attr':{'class':'control label'}}}}
{{form_小部件(form.name,{'attr':{'class':''}}}}
{{form_errors(form.name)}}
{{form_标签(form.orderSequence,'Rang',{'attr':{'class':'control label'}}}}}
{{form_小部件(form.orderSequence,{'attr':{'class':''}}}}
{{form_errors(form.orderSequence)}}
{{form_标签(form.image,'image',{'attr':{'class':'control label'}}}}
{{form_小部件(form.image,{'attr':{'class':''}}}}
{{form_errors(form.image)}}
{{form_rest(form)}
登记员

Symfony2区分了单个类的单元测试和应用程序行为的功能测试。单元测试是通过直接实例化一个类并对其调用方法来执行的。功能测试通过模拟请求和测试响应来执行。有关更多详细信息,请参阅

表单提交只能在功能上进行测试,因为它由始终在容器上下文中运行的Symfony控制器处理。Symfony功能测试必须扩展WebTestCase类。此类提供对客户端的访问,该客户端用于请求URL、单击链接、选择按钮和提交表单。这些操作返回一个表示HTML响应的爬虫程序实例,该实例用于验证响应是否包含预期内容

只适合在执行单元测试时测试抛出异常,因为功能测试包括与用户的交互。用户永远不应该知道抛出了异常。因此,最坏的情况是Symfony捕捉到异常,并且在生产过程中,向用户显示catch all响应“Oops,发生错误”(或类似的定制消息)。但是,这应该只在应用程序损坏时发生,而不是因为用户错误地使用了应用程序。因此,它不是通常在功能测试中测试的东西

关于问题中提到的第一个场景-提交带有错误参数的表单。在这种情况下,应该向用户显示一条错误消息,告诉他们输入有什么问题。理想情况下,控制器不应引发异常,但应根据情况自动在每个字段旁边生成错误消息。无论错误如何显示,都可以通过检查提交表单的响应是否包含预期的错误来测试。例如:

class MyControllerTest extends WebTestCase
{
    public function testCreateUserValidation()
    {
        $client = static::createClient();
        $crawler = $client->request('GET', '/new-user');
        $form = $crawler->selectButton('submit')->form();
        $crawler = $client->submit($form, array('name' => '', 'email' => 'xxx'));
        $this->assertTrue($crawler->filter('html:contains("Name must not be blank")')->count() > 0,
                          "Page contains 'Name must not be blank'");
        $this->assertTrue($crawler->filter('html:contains("Invalid email address")')->count() > 0,
                          "Page contains 'Invalid email address'");
    }
}
关于第二种情况——URL不完整。对于Symfony,任何与已定义路由不匹配的URL都将导致NotFoundHttpException。在开发过程中,这将导致一条消息,如“找不到“GET/xxx”的路由”。在生产中,它将导致“Oops,发生了错误”的全面捕获。可以在开发中测试响应是否包含“未找到路由”。然而,在实践中,测试它并没有真正意义,因为它是由Symfony框架处理的,因此是给定的

编辑:

关于URL包含标识对象的无效数据的场景。这可以在单元测试程序中进行测试(开发中):

$client = static::createClient();

$page = $client->request('GET', '/update/XXX');
$exceptionThrown = ($page->filter('html:contains("NotFoundException")')->count() > 0) && ($page->filter('html:contains("Unable to find ParkingZone entity")')->count() > 0);
$this->assertTrue($exceptionThrown, "Exception thrown 'Unable to find ParkingZone entity'");
$client = static::createClient();
$session = $client->getContainer()->get('session');
$session->set('formAction', '/test/route');
$session->save();

// do the test

如果您只是想测试是否引发了异常,而不是特定的类型/消息,那么您可以在html中筛选“异常”。请记住,在生产过程中,用户只会看到“Oops,发生了错误”,单词“Exception”将不存在。

Symfony本身没有任何对象,当表单在html(小树枝文件)中设置时,可以通过这些对象操纵表单的操作。但是,twig提供了在twig文件中动态更改表单操作的功能

基本方法是控制器通过渲染调用将参数传递到细枝文件中。然后细枝文件可以使用此参数动态设置表单操作。如果控制器使用会话变量来确定此参数的值,则通过在测试程序中设置此会话变量的值,可以专门为测试设置窗体操作

例如,在控制器中:

public function indexAction()
{
    $session = $this->get('session');
    $formAction = $session->get('formAction');
    if (empty($formAction)) $formAction = '/my/normal/route';

    ...

    return $this->render('MyBundle:XXX:index.html.twig', array(
        'form' =>  $form->createView(), 'formAction' => $formAction)
    );
}
然后,在细枝文件中:

<form id="myForm" name="myForm" action="{{ formAction }}" method="post">
...
</form>

这不是唯一的方法,有各种可能性。例如,会话变量可以是$testMode,如果设置了该变量,则表单会将$testMode=true传递到呈现调用中。然后,twig文件可以根据testMode变量的值将form action设置为两个值之一。

多亏了@redbirdo的最后一个答案,我找到了一个解决方案,而没有弄乱控制器。 我只更改了模板中的几行

控制器测试

public function testUpdate()
{
    $client = static::createClient();
    $session = $client->getContainer()->get('session');
    $session->set('testActionForm', 'abc');
    $session->save();       // This line is important or you template won't see the variable

    // ... tests
}
查看

{% if app.session.has('testActionForm') %}
    {% set actionForm = path('parkingzone_update', { 'id': app.session.get('testActionForm') }) %}
{% else %}
    {% set actionForm = path('parkingzone_update', { 'id': entity.id }) %}
{% endif %}

<form action="{{ actionForm }}" {{ form_enctype(form) }} method="POST" class="form-horizontal">
// ... rest of the form
{%if app.session.ha
public function testUpdate()
{
    $client = static::createClient();
    $session = $client->getContainer()->get('session');
    $session->set('testActionForm', 'abc');
    $session->save();       // This line is important or you template won't see the variable

    // ... tests
}
{% if app.session.has('testActionForm') %}
    {% set actionForm = path('parkingzone_update', { 'id': app.session.get('testActionForm') }) %}
{% else %}
    {% set actionForm = path('parkingzone_update', { 'id': entity.id }) %}
{% endif %}

<form action="{{ actionForm }}" {{ form_enctype(form) }} method="POST" class="form-horizontal">
// ... rest of the form