• 3rd, May 2011

Testing Zend Database Model with PHPUnit on Zend Studio

I’ve been trying to create database test cases. Finally this is the way I had to do it.
You should have the Controller Test Cases running and phpunit.xml configured properly.

Notes: The model class to test is called “Project”.

1) Add Libraries to the project
- Right click on the project
- PHP Include Path
- Add external source folder: /Applications/MAMP/bin/php5.3/lib/php/ZendFramework-1.11.5/library
(your Zend Framework version library)
- Add external source folder: /Applications/Zend Studio.app/Contents/Resources/Java/plugins/com.zend.php.phpunit_8.0.0.v20101001-0100/resources/library
(your Zend Studio phpunit plugin)
Zend Studio - PHP Include Path

 

2) MyProject/application/configs/application.ini

...
[testing : production]
resources.db.adapter = "pdo_mysql"
resources.db.params.host = 127.0.0.1
resources.db.params.port = 8889
resources.db.params.username = root
resources.db.params.password = root
resources.db.params.dbname = "test_myproject_com"
xmlseeds.folder = APPLICATION_PATH "/../tests/xmlseeds/"
...

3) Create folders and file MyProject/library/Application/Test/PHPUnit/DatabaseTestCase/Abstract.php

<?php
/**
 * Database test case
 *
 * Encapsulate reusable code for DB testing, providing methods to compare
 * DB results with expected data stored in XML files.
 *
 * @package Library
 */

require_once 'PHPUnit/Extensions/Database/DataSet/DefaultDataSet.php';

abstract class Application_Test_PHPUnit_DatabaseTestCase_Abstract extends Zend_Test_PHPUnit_DatabaseTestCase
{
    const DEFAULT_CONNECTION_SCHEMA = 'main';

    /**
     * Variable to be defined in each test case
     *
     * @var string
     */
    protected $_initialSeedFile = '';

    /**
     * Allow to override the global configuration for a particular test case
     *
     * @var string
     */
    protected $_seedFilesPath = NULL;

    /**
     * Parameter for Zend_Test_PHPUnit_Db_Connection
     *
     * @var string
     */
    protected $_connectionSchema = self::DEFAULT_CONNECTION_SCHEMA;

    /**
     * Connection to testing database
     *
     * @var Zend_Test_PHPUnit_Db_Connection
     */
    protected $_connectionMock;

    /**
     * Application configuration
     *
     * @var Zend_Config_Ini
     */
    private $__configuration = NULL;

    /**
     * Returns the application configuration
     *
     * @return Zend_Config_Ini
     */
    public function getConfiguration()
    {
        if ($this->__configuration == NULL) {
            $this->__configuration = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', APPLICATION_ENV);
        }

        return $this->__configuration;
    }

    /**
     * Returns the seed files folder path
     *
     * @return string
     */
    public function getSeedFilesPath()
    {
        if ($this->_seedFilesPath == NULL) {
            $this->_seedFilesPath = $this->getConfiguration()->xmlseeds->folder;
        }

        return rtrim($this->_seedFilesPath, '/') . '/';
    }

    /**
     * Returns the test database connection.
     *
     * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
     */
    protected function getConnection()
    {
        if ($this->_connectionMock == NULL) {
            $dbAdapterName = $this->getConfiguration()->resources->db->adapter;
            $dbAdapterParams = $this->getConfiguration()->resources->db->params->toArray();

            $connection = Zend_Db::factory($dbAdapterName, $dbAdapterParams);

            $this->_connectionMock = $this->createZendDbConnection(
                $connection, $this->_connectionSchema
            );

            Zend_Db_Table_Abstract::setDefaultAdapter($connection);
        }
        return $this->_connectionMock;
    }

    /**
     * Retrieve from flat XML files data used to populate the database
     *
     * @return PHPUnit_Extensions_Database_DataSet_IDataSet
     */
    protected function getDataSet()
    {
        return $this->createFlatXmlDataSet($this->getSeedFilesPath() . $this->_initialSeedFile);
    }

    /**
     * Convert a Rowset to a Dataset
     *
     * @param  Zend_Db_Table_Rowset_Abstract $rowset
     * @param  string $tableName
     * @return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
     */
    public function convertRowsetToDataSet($rowset, $tableName = NULL)
    {
        $rowsetDataSet = new Zend_Test_PHPUnit_Db_DataSet_DbRowset($rowset, $tableName);
        return new PHPUnit_Extensions_Database_DataSet_DefaultDataSet(array($rowsetDataSet));
    }

    /**
     * Convert a Record to a Dataset
     *
     * @param  array $data
     * @param  string $tableName
     * @return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
     */
    public function convertRecordToDataSet(Array $data, $tableName)
    {
        $rowset = new Zend_Db_Table_Rowset(array('data' => array($data)));
        return $this->convertRowsetToDataSet($rowset, $tableName);
    }

    /**
     * Compare dataset with data stored in the file
     *
     * @param  string $filename
     * @param  PHPUnit_Extensions_Database_DataSet_IDataSet $expected
     * @return boolean
     */
    public function assertDataSetsMatchXML($filename, PHPUnit_Extensions_Database_DataSet_IDataSet $actual)
    {
        if (empty($filename) || !is_string($filename))
                throw new InvalidArgumentException(
                  'Second parameter "filename" is not a valid string.'
                );

        $expected = $this->createFlatXmlDataSet($this->getSeedFilesPath() . $filename);

        return $this->assertDataSetsEqual($expected, $actual);
    }
}

4) Create folders and file MyProject/tests/application/models/ProjectTest.php

require '../library/Application/Test/PHPUnit/DatabaseTestCase/Abstract.php';

class Application_Model_ProjectTest extends Application_Test_PHPUnit_DatabaseTestCase_Abstract
{
    protected $_initialSeedFile = 'project.xml';

    public function testSaveInsert()
    {
        $data = array(
            'name' => 'Test Project Model'
             );

        $model = new Application_Model_Project($data);

        $userMapper = new Application_Model_ProjectMapper();

        // exercise
        $userMapper->save($model);

        // get data from the testing database
        $dataSet = new Zend_Test_PHPUnit_Db_DataSet_QueryDataSet($this->getConnection());
        $dataSet->addTable('project', 'SELECT * FROM project');

        // verify expected vs actual
        $this->assertDataSetsMatchXML('projectInsertIntoAssertion.xml', $dataSet);
    }

5) Create file /tests/xmlseeds/project.xml

<?xml version="1.0" encoding="UTF-8" ?>
<dataset>
  <project project_id="1" name="Project Test 1" />
  <project project_id="2" name="Project Test 2" />
</dataset>

6) Create file /tests/xmlseeds/projectInsertIntoAssertion.xml

<?xml version="1.0" encoding="UTF-8" ?>
<dataset>
  <project project_id="1" name="Project Test 1" />
  <project project_id="2" name="Project Test 2" />
  <project project_id="3" name="Test Project Model" />
</dataset>
 

Zend Studio Run As PHPUnit

 

Zend Studio PHPUnit results

References:
http://framework.zend.com/manual/en/zend.test.phpunit.db.html
http://techportal.ibuildings.com/2010/12/07/unit-testing-databases-with-zend-framework/

Argument 1 passed to PHPUnit_Extensions_Database_DataSet_DefaultTableIterator :: __construct() must be an array, null given, called in /usr/…DataSet/AbstractXmlDataSet.php on line 134 and defined

Click here to submit your review.


Submit your review
* Required Field

Tags: , , , , , ,

Leave a Reply

*

© 2010 unexpected[it]. All Rights Reserved.