Я использую CSRF скрытый элемент хэша с Zend_Form и пытаюсь выполнить Unit Test, но не знаю, как написать Unit Test, чтобы включить этот элемент. Посмотрел в документах и прочитал столько уроков, сколько мог найти. Я даже delicioused them all, но никто не упоминает об этом.Как вы тестируете модуль Zend_Form, который включает элемент формы CSRF?
ответ
Правильный хэш сохраняется в сеансе, а элемент формы Хэш имеет экземпляр Zend_Session_Namespace, который содержит пространство имен для хэша.
Для модульного тестирования элементов, вы бы заменить экземпляр Zend_Session_Namespace в элементе (с setSession) с одним вы создаете сами, который содержит правильный хэш (хэш хранится в ключ «хэш»)
Для дальнейшего например, вы могли бы, вероятно, посмотреть на модульные тесты Zend Framework для класса Zend_Form_Element_Hash. Я бы предположил, что им пришлось иметь дело с этим.
Я чувствую, что что-то не так, когда вы должны знать, что многое о реализации CSRF для написания тестов для контроллеров, которые его используют. –
В более ограниченном случае вы, вероятно, заменили бы весь элемент формы CSRF на насмешливый экземпляр, тогда вам не нужно будет разбираться с файлом хранения сеанса –
я установить переменные окружения в моем ВХосте файл Apache, который указует код, который сервер это работает на: развития, постановку или производство
Линии для файла ВХоста является:
SetEnv SITE_ENV "dev"
Тогда я просто сделать мои формы реагируют на соответствующую среду:
if($_SERVER['SITE_ENV']!='dev')
{
$form_element->addValidator($csrf_validator);
}
Я использую эту же технику для большого количества вещей. Например, если это dev, я перенаправляю все исходящие письма мне и т. Д.
Это похоже на то, что я закончил делать в файле forms.ini ... Я не знаю, почему, но не поклонник выражений IF за пределами лесов или .ini-файлов для обработки, относящейся к окружающей среде, в основном коде. Просто кажется, что новая среда потребует поискать в тоннах мест, чтобы исправить это, а не .ini и bootstrap, где вы ожидаете различий .... – joedevon
Значение 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');
// ...
}
Это выглядит многообещающим, однако '$ html = $ this-> getResponse() -> getBody(); 'всегда пусто в моем случае. – takeshin
@takeshin не забудьте отправить страницу с формой, прежде чем просить тело;) –
# на сегодняшний день я выполнил модульные тесты с использованием этого подхода, и он работает. +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, и вы в конечном итоге будете использовать обычный хеш-элемент. Вы узнаете, что используете обычный хэш-элемент, потому что вы, вероятно, получите некоторую ошибку сеанса, если вы НЕ подключены к базе данных.
Дайте мне знать, если вы найдете это полезное или используете его.
Раствор для 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);
спасибо, что вы меня очень долго спасли – Hooli
Обновление: Это немного запутано, но я был в состоянии получить проверяемые форму, потому что я загрузка мой Zend_Form из .ini-файла. Я разделил раздел csrf на раздел только для тестирования, поэтому мои тесты позволяют войти в систему без прохождения через csrf. Надеюсь, это помогает кому-то другому. Кстати, я думаю, что .ini-файл - лучшее место для загрузки ваших форм. – joedevon
Создатель PHPUnit упомянул мне, что «сквозное тестирование! = Unit Testing», что верно, конечно. В этом случае я не заботился о том, чтобы получить csrf в той мере, насколько я хотел проверить, что я могу войти в систему и увидеть какой-то элемент на результирующей странице. Невозможность включить этот элемент в тест убила логин ... – joedevon