i was just reading a great presentation about Quality Assurance for PHP Projects by Michelangelo van Dam aka DragonBe. In his presentation he uses Zend-Framework as an example, which i am familiar with on a basic level.
Since i want to improve myself, im starting with unit testing, though i feel the problem is on ZFs side.
The Problem:
With given code-artifacts whenever i assign a boolean value of false the Zend_Filter or Zend_Validator changes this into null. I can’t figure out why this is the case.
Please see update on bottom for newer code and test
First the Tests
public function goodData() {
return array(
array('DU-IT', 'Sample Description', true, false),
array('Mercüß', 'bla"ß"trager', false, true),
array('Mia123', '728 Tage im Jahr', false, false)
);
}
/**
* @dataProvider goodData()
*/
public function testModelAcceptsValidData($name, $description, $flag_active, $flag_deleted)
{
$data = array(
'id' => 0,
'name' => $name,
'description' => $description,
'flag_active' => $flag_active,
'flag_deleted' => $flag_deleted
);
try {
$this->_model->populate($data);
} catch (Zend_Exception $e) {
$this->fail('Unexpected Exception: '.$e->getMessage());
}
$this->assertSame($data, $this->_model->toArray());
}
The Model
public function __construct($props = null)
{
// Set Filters
$this->_filters = array(
'id' => array('Int'),
'name' => array('StringTrim', 'StripTags'),
'description' => array('StringTrim', 'StripTags'),
'flag_active' => array(new Zend_Filter_Boolean()),
'flag_deleted' => array(new Zend_Filter_Boolean())
);
// Set Validators
$this->_validators = array(
'id' => array('Int'),
'name' => array(new Zend_Validate_StringLength(array('min'=>4, 'max'=>50))),
'description' => array(new Zend_Validate_StringLength(array('max'=>5000))),
'flag_active' => array(new Zend_Validate_InArray(array(true, false))),
'flag_deleted' => array(new Zend_Validate_InArray(array(true, false)))
);
// Set Properties
if (!is_null($props)) {
$this->populate($props);
}
}
public function setFlagActive($arg)
{
$input = new Zend_Filter_Input($this->_filters, $this->_validators);
$input->setData(array('flag_active'=>$arg));
if (!$input->isValid('flag_active')) {
throw new Zend_Exception('Invalid FLAG_ACTIVE provided'. gettype($input->flag_active));
}
$this->_flag_active = (bool) $input->flag_active;
return $this;
}
As far as the model is concerned, i tried leaving the validator for flag_active and flag_deleted empty, but this did not change my results. The error message of phpunit remains the same:
Unexpected Exception: Invalid FLAG_ACTIVE providedNULL
Whereas NULL is the type of the variable, WHENEVER i pass false as the argument for the flag via the data-provider goodData() (same happens with badData, too).
My guess is this has something to do with Zend_Filter, but i just can’t figure this out. And hints are greatly appreciated!
UPDATE
Since Drew gave a little hint i’ve tested a little further, yet the problem remains. I have pasted the updated Class and unit test onto pastebin for better readability.
PHPUnit gives out the following error: You must give a non-empty value for field 'flag_active' same for flag_deleted. A second error on half the tests is <null> does not match expected type "boolean". I’m stuck. No matter if i use filters or an inArrayValidator(array(0=>true,1=>false)) it doesn’t change a thing :\
If you examine the contents of
$input->getMessages(), it should provide some explanation as to why that particular value is coming through as invalid.When you use
Zend_Filter_Input, any value that did not pass validation will not be magically accessible by its name (e.g.$input->flag_active). The value will always beNULLif it didn’t pass the validation step.Certain filters can almost guarantee validation in some cases (i.e. an Int filter with an Int validator) because the filter will filter the data and return a valid value for the validator. Passing
hellothrough theIntfilter returns0which may validate with a simpleIntvalidator even though the original input data is not valid.The reason you are most likely getting a null value within your exception is because the value is not available since it didn’t validate; therefore check the input messages for any hints as to why.
EDIT:
I think the problem you are having is that
Zend_Filter_Inputis not allowing empty values by default. Therefore if the value coming into the filter isfalseorNULL, it is causing an error with the filter.Check out this code:
So the problem seems to be that Zend_Filter_Input doesn’t like empty values unless you specify an option. Therefore sending a valid (
false) value into the filter causes an error unless you setZend_Filter_Input::ALLOW_EMPTYtotrue.