2009-07-10 5 views
6

Я использую CSRF скрытый элемент хэша с Zend_Form и пытаюсь выполнить Unit Test, но не знаю, как написать Unit Test, чтобы включить этот элемент. Посмотрел в документах и ​​прочитал столько уроков, сколько мог найти. Я даже delicioused them all, но никто не упоминает об этом.Как вы тестируете модуль Zend_Form, который включает элемент формы CSRF?

+1

Обновление: Это немного запутано, но я был в состоянии получить проверяемые форму, потому что я загрузка мой Zend_Form из .ini-файла. Я разделил раздел csrf на раздел только для тестирования, поэтому мои тесты позволяют войти в систему без прохождения через csrf. Надеюсь, это помогает кому-то другому. Кстати, я думаю, что .ini-файл - лучшее место для загрузки ваших форм. – joedevon

+0

Создатель PHPUnit упомянул мне, что «сквозное тестирование! = Unit Testing», что верно, конечно. В этом случае я не заботился о том, чтобы получить csrf в той мере, насколько я хотел проверить, что я могу войти в систему и увидеть какой-то элемент на результирующей странице. Невозможность включить этот элемент в тест убила логин ... – joedevon

ответ

3

Правильный хэш сохраняется в сеансе, а элемент формы Хэш имеет экземпляр Zend_Session_Namespace, который содержит пространство имен для хэша.

Для модульного тестирования элементов, вы бы заменить экземпляр Zend_Session_Namespace в элементе (с setSession) с одним вы создаете сами, который содержит правильный хэш (хэш хранится в ключ «хэш»)

Для дальнейшего например, вы могли бы, вероятно, посмотреть на модульные тесты Zend Framework для класса Zend_Form_Element_Hash. Я бы предположил, что им пришлось иметь дело с этим.

+0

Я чувствую, что что-то не так, когда вы должны знать, что многое о реализации CSRF для написания тестов для контроллеров, которые его используют. –

+0

В более ограниченном случае вы, вероятно, заменили бы весь элемент формы CSRF на насмешливый экземпляр, тогда вам не нужно будет разбираться с файлом хранения сеанса –

1

я установить переменные окружения в моем ВХосте файл Apache, который указует код, который сервер это работает на: развития, постановку или производство

Линии для файла ВХоста является:

SetEnv SITE_ENV "dev" 

Тогда я просто сделать мои формы реагируют на соответствующую среду:

if($_SERVER['SITE_ENV']!='dev') 
{ 
    $form_element->addValidator($csrf_validator); 
} 

Я использую эту же технику для большого количества вещей. Например, если это dev, я перенаправляю все исходящие письма мне и т. Д.

+0

Это похоже на то, что я закончил делать в файле forms.ini ... Я не знаю, почему, но не поклонник выражений IF за пределами лесов или .ini-файлов для обработки, относящейся к окружающей среде, в основном коде. Просто кажется, что новая среда потребует поискать в тоннах мест, чтобы исправить это, а не .ini и bootstrap, где вы ожидаете различий .... – joedevon

9

Значение Csrf генерируется каждый раз, когда отображается форма. Скрытый элемент формы получает заданное значение. Это значение также сохраняется в сеансе. После отправки формы проверки проверки, если значение, отправленное из формы, сохраняется в сеансе, если нет, то проверка не выполняется. Очень важно, чтобы форма была визуализирована во время теста (чтобы она могла сгенерировать скрытое значение и сохранить его в сеансе), тогда мы можем извлечь скрытое значение из отображаемого html, а затем мы можем добавить скрытое значение хэша в наш запрос. Рассмотрим следующий пример:

function testAddPageStoreValidData() 
{ 
    // render the page with form 
    $this->dispatch('/form-page'); 

    // fetch content of the page 
    $html = $this->getResponse()->getBody(); 

    // parse page content, find the hash value prefilled to the hidden element 
    $dom = new Zend_Dom_Query($html); 
    $csrf = $dom->query('#csrf')->current()->getAttribute('value'); 

    // reset tester for one more request 
    $this->resetRequest() 
     ->resetResponse(); 

    // now include $csrf value parsed from form, to the next request 
    $this->request->setMethod('POST') 
        ->setPost(array('title'=>'MyNewTitle', 
            'body'=>'Body', 
            'csrf'=>$csrf)); 
    $this->dispatch('/form-page'); 

    // ... 
} 
+0

Это выглядит многообещающим, однако '$ html = $ this-> getResponse() -> getBody(); 'всегда пусто в моем случае. – takeshin

+0

@takeshin не забудьте отправить страницу с формой, прежде чем просить тело;) –

+0

# на сегодняшний день я выполнил модульные тесты с использованием этого подхода, и он работает. +1 к Лукасу. –

1

Я ответил на более позднюю вопрос, подобный этому. Я также ставил свой ответ на случай, если он поможет кому-либо в будущем.

Недавно я нашел отличный способ тестирования форм с элементами хэша. Это будет использовать макет объекта, чтобы заглушить хэш-элемент, и вам не придется беспокоиться об этом. Вам даже не придется делать session_start или что-то в этом роде. Вам также не придется «прервать» форму.

Сначала создайте «заглушки» класс как так

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 
    } 
} 

Метод установки существует только для целей тестирования. Вы, вероятно, не будете использовать его вообще во время реального использования, но теперь в 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(), потому что это будет напрямую расширять хеш-элемент, а обычный хеш-элемент делает «зло» в своем конструкторе.

С помощью этого метода вам даже не нужно подключаться к базе данных для проверки ваших форм! Мне потребовалось некоторое время, чтобы подумать об этом.

Если вы хотите, вы можете нажать метод setHashElement() (наряду с переменной и методом get) в некоторый базовый класс FormAbstract.

ПОМНИТЕ, в phpunit, вы должны передать элемент хеша во время построения формы. Если вы этого не сделаете, ваш метод init() будет вызван до того, как ваш хэш-заглушка может быть задан с помощью метода set, и вы в конечном итоге будете использовать обычный хеш-элемент. Вы узнаете, что используете обычный хэш-элемент, потому что вы, вероятно, получите некоторую ошибку сеанса, если вы НЕ подключены к базе данных.

Дайте мне знать, если вы найдете это полезное или используете его.

1

Раствор для ZF2 создает свою форму в тесте, и получать отдачу от CSRF элемента формы:

 $form = new \User\Form\SignupForm('create-user'); 
     $data = [ 
      'security' => $form->get('security')->getValue(), 
      'email' => '[email protected]', 
      'password' => '123456', 
      'repeat-password' => '123456', 
     ]; 
     $this->dispatch('/signup', 'POST', $data); 
+0

спасибо, что вы меня очень долго спасли – Hooli

 Смежные вопросы

  • Нет связанных вопросов^_^