PHPUnit/DBUnit Handle Timestamp Column
-
18-06-2021 - |
سؤال
I am trying to use PHPUnit/DBUnit to test my Zend Framework DbTable models. I am getting tripped up with tables that have a timestamp.
I am trying to use assertDataSetsEqual to compare an the actual results of an insert to the expected results. Of course, when I insert a record into a table with a timestamp, the timestamp field get populated with the current date/time. The dataset that represents the expected data is static so the timestamp won't match.
How can I handle this situation? Can I make the assertion ignore the timestamp column?
المحلول
I just found a much better solution to this thanks to this blog post.
I created a function to allow me to easily assert my two datasets are equal.
protected function assertDataSetEquals(
$ExpectedXMLFileName,
array $options = array()) {
$model = (isset($options['model'])) ?
$options['model'] :
$this->_object;
$excludeColumns = (isset($options['excludeColumns'])) ?
$options['excludeColumns'] :
null;
$ds = new Zend_Test_PHPUnit_Db_DataSet_DbTableDataSet();
$ds->addTable($model);
$dsFiltered = (isset($excludeColumns)) ?
$this->filterColumns($model, $ds, $excludeColumns) :
$ds;
$this->assertDataSetsEqual(
$this->createFlatXmlDataSet(
APPLICATION_PATH
. '/../tests/fixtures/models/'
. $ExpectedXMLFileName . '.xml'
),
$dsFiltered
);
}
And a private function to return the filtered dataset.
private function filterColumns(
$model,
$dataSet,
$excludeColumns) {
$dsFiltered =
new PHPUnit_Extensions_Database_DataSet_DataSetFilter($dataSet);
$dsFiltered->setExcludeColumnsForTable(
$model->getName(),
$excludeColumns
);
return $dsFiltered;
}
Now to compare two datasets while excluding any columns I just do this.
$this->assertDataSetEquals(
'TableWithTimestampIWantToIgnoreUpdate',
array('excludeColumns'=>array('timestamp','id'))
);
This makes for a much easier/cleaner way to test models that correspond to tables with a timestamp column.
نصائح أخرى
I haven't found anything that makes me think this is possible.
The way I eventually solved it was to query the table after the update, saving the results in an array, then using assertEquals to insure the proper fields were updated.
Thanks to bconrad, I added this function in my test class:
/**
* @param Zend_Test_PHPUnit_Db_DataSet_QueryDataSet $dataSet
* @param array $excludeTheseColumnsOfTheseTables Array where the keys are table names and the values are arrays of column names to exclude.
* @return PHPUnit_Extensions_Database_DataSet_DataSetFilter
* @see http://stackoverflow.com/a/11636295/470749
*/
protected function filterColumns($dataSet, $excludeTheseColumnsOfTheseTables)
{
$filteredDataset = new \PHPUnit_Extensions_Database_DataSet_DataSetFilter($dataSet);
foreach ($excludeTheseColumnsOfTheseTables as $tableName => $excludedColumns) {
$filteredDataset->setExcludeColumnsForTable($tableName, $excludedColumns);
}
return $filteredDataset;
}
Then filtering a dataset is as easy as this:
$queryDataSet = new \Zend_Test_PHPUnit_Db_DataSet_QueryDataSet($this->getConnection());
$queryDataSet->addTable('posts', 'SELECT * FROM posts');
$queryDataSet->addTable('users', 'SELECT * FROM users');
$excludeTheseColumnsOfTheseTables = array(
'users' => array('created', 'modified'),
'posts' => array('modified'));
$filteredDataset = $this->filterColumns($queryDataSet, $excludeTheseColumnsOfTheseTables);
$this->assertDataSetsEqual($this->getAssertionXmlDataSet('asrt.xml'), $filteredDataset);