Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top