在Zend Framework中具有哈希元素的单元测试表单

时间:2011-02-22 09:57:15

标签: zend-framework phpunit

我正在尝试在我的一个Zend_Forms中测试有效的表单数据,但是由于它具有随机生成的哈希元素而导致它失败,我无法访问生成的哈希将其重新置于断言数据中。 E.g。

$form = new MyForm();
$data = array('username'=>'test');
$this->assertTrue($form->isValid($data));

由于它不包含哈希元素值,因此失败。

3 个答案:

答案 0 :(得分:4)

当我的表格有验证码时,我遇到了同样的问题,我想测试一下。我无法思考的两种可能的解决方案:

  1. 首先渲染表单(然后生成哈希),然后获取该元素,获取值并使用它来测试表单。
  2. 只需删除哈希元素即可进行测试。

答案 1 :(得分:3)

谢谢单打。在测试之前渲染表单完全适用于我的问题。我不会太高兴删除哈希元素进行测试:

  1. 您将添加一定数量的 无意义的代码来删除这些 测试期间的元素。
  2. 还需要测试安全功能。
  3. 以下是我如何做到这一点的简单示例:

    public function testLoginSetsSession()
    {
        // must render the form first to generate the CSRF hash
        $form = new Form_Login();
        $form->render();
    
        $this->request
             ->setMethod('POST')
             ->setPost(array(
                 'email' => 'test@test.co.uk',
                 'password' => 'password',
                 'hash' => $form->hash->getValue()
             ));
        $this->dispatch('/login');
    
        $this->assertTrue(Zend_Auth::getInstance()->hasIdentity());
    }
    

答案 2 :(得分:1)

我最近发现了一种使用哈希元素测试表单的好方法。这将使用模拟对象来删除哈希元素,您不必担心它。你甚至不需要这样做session_start或任何东西。您也不必“预呈现”表格。

首先创建一个'stub'类,如此



    class My_Form_Element_HashStub extends Zend_Form_Element_Hash
    {
        public function __construct(){}
    }


然后,将以下内容添加到表单中。


    class MyForm extends Zend_Form{

    protected $_hashElement;

    public function setHashElement( Zend_Form_Hash_Element $hash )
    { 
      $this->_hashElement = $hash; 
      return $this; 
    }

    protected function _getHashElement( $name = 'hashElement' )
    { 
      if( !isset( $this->_hashElement )
      {
          if( isset( $name ) )
          {
                $element = new Zend_Form_Element_Hash( $name, 
                                                      array( 'id' => $name ) );
          }
          else
          {
                $element = new Zend_Form_Element_Hash( 'hashElement', 
                                            array( 'id' => 'hashElement' ) );
          }

         $this->setHashElement( $element );
         return $this->_hashElement;
      }
    }
    /**
     *
     * In your init method you can now add the hash element like below
     *
     *
     *
     */

    public function init()
    {
        //other code
        $this->addElement( $this->_getHashElement( 'myotherhashelementname' );
        //other code
    }

set方法仅用于测试目的。在实际使用中你可能根本不会使用它,但是现在你可以在phpunit中使用以下内容。

class My_Form_LoginTest
        extends PHPUnit_Framework_TestCase
{

    /**
     *
     * @var My_Form_Login
     */
    protected $_form;
    /**
     *
     * @var PHPUnit_Framework_MockObject_MockObject
     */
    protected $_hash;

    public function setUp()
    {
        parent::setUp();
        $this->_hash = $this->getMock( 'My_Form_Element_HashStub' );

        $this->_form = new My_Form_Login( array(
                    'action'                    => '/',
                    'hashElement'               => $this->_hash
    }

    public function testTrue()
    {   
        //The hash element will now always validate to true
        $this->_hash
             ->expects( $this->any() )
             ->method( 'isValid' )
             ->will( $this->returnValue( true ) );

        //OR if you need it to validate to false
                $this->_hash
             ->expects( $this->any() )
             ->method( 'isValid' )
             ->will( $this->returnValue( true ) );

    }

您必须创建自己的存根。你不能只调用phpunit方法getMockObject,因为它会直接扩展hash元素,而普通的hash元素会在其构造函数中执行'evil'。

使用此方法,您甚至无需连接到数据库来测试表单!我花了一段时间才想到这一点。

如果需要,可以将setHashElement方法(以及变量和get方法)推送到某个FormAbstract基类中。

请记住,在phpunit中,您必须在表单构造期间传递哈希元素。如果不这样做,则在使用set方法设置存根哈希之前将调用init方法,并且最终将使用常规哈希元素。你会知道你正在使用常规哈希元素,因为如果你没有连接到数据库,你可能会遇到一些会话错误。

如果您觉得有用或者使用它,请告诉我。