ZF-8087: Error within unit testing with PHPUnit - Zend_Db_Table_Exception: No adapter found for [...]

Description

I am using TDD with Zend Framework.

I've set up tests for every component of my application. Within testing, I am using an SQLite database that replaces the live database.

With 1.8.4, all went well.

With 1.9, I am getting random errors during testing, for example the following:

7) ModelTechnologyMapperTest::testFetchAll Zend_Db_Table_Exception: No adapter found for Default_Model_DbTable_Technologies

/Users/skiller/PHP Projects/skiller/library/Zend/Db/Table/Abstract.php:754 /Users/skiller/PHP Projects/skiller/library/Zend/Db/Table/Abstract.php:739 /Users/skiller/PHP Projects/skiller/library/Zend/Db/Table/Abstract.php:268 /Users/skiller/PHP Projects/skiller/application/models/TechnologyMapper.php:17 /Users/skiller/PHP Projects/skiller/application/models/TechnologyMapper.php:32 /Users/skiller/PHP Projects/skiller/application/models/TechnologyMapper.php:52 /Users/skiller/PHP Projects/skiller/tests/application/models/TechnologyMapperTest.php:86

The strange thing is that other tests for model classes in the same test suite don't yield such errors although they share the exact same database and configuration parameters.

Since some tests work and some don't, I suspect a problem with the correct initiation sequence within the extended ZF/PHPUnit framework.

Comments

Could you please provide any code with which we can reproduce this problem?

(I hope this is rendered readably by JIRA)

phpunit.xml (in tests/):

<?xml version="1.0" encoding="utf-8"?>
./../application../application../application/Bootstrap.php../application/controllers/ErrorController.php

in application.ini:

---8<--- snip ---8<---
[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
phpSettings.date.default.timezone = "Europe/Vienna"
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
resources.view[] =
---8<--- snip ---8<---

---8<--- snip ---8<---
[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.db.adapter = "Pdo_Sqlite"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/sitedata-testing.db"

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
;resources.db.adapter = "Pdo_Mysql"
;resources.db.params.host = "localhost"
---8<--- snip ---8<---

in tests/TechnologyMapperTest.php

<?php
class ModelTechnologyMapperTest extends ControllerTestCase {

    /**
     * @var Default_Model_TechnologyMapper
     */
    protected $_mapper;

    public function setUp() {
        $this->_mapper = new Default_Model_TechnologyMapper();
    }

    public function tearDown() {
        $this->_mapper->getDbTable()
            ->delete(array("order_index = ?" => -101));
        $this->_mapper->getDbTable()
            ->delete(array("order_index = ?" => -100));
    }

    public function testDbTableProperty() {
        $this->assertClassHasAttribute("_dbTable", "Default_Model_TechnologyMapper");
    }
---8<--- snip ---8<---

in application/models/TechnologyMapper.php:

<?php
class Default_Model_TechnologyMapper {
    /**
     * The database table object
     *
     * @var Default_Model_DbTable_Technologies
     */
    protected $_dbTable;

    /**
     * Set the table object
     * @param $dbTable
     * @return Default_Model_TechnologyMapper
     */
    public function setDbTable($dbTable) {
        if (is_string ( $dbTable )) {
            $dbTable = new $dbTable ( );
        }
        if (! $dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception ( "Invalid table data gateway provider" );
        }
        $this->_dbTable = $dbTable;
        return $this;
    }

    /**
     * Get the table object
     * @return Default_Model_DbTable_Technologies
     */
    public function getDbTable() {
        if (null === $this->_dbTable) {
            $this->setDbTable ( "Default_Model_DbTable_Technologies" );
        }
        return $this->_dbTable;
    }

    /**
     * Save a technology
     * @param Default_Model_Technology $tech
     * @return Default_Model_TechnologyMapper
     */
    public function save(Default_Model_Technology &$tech) {
        $data = array(
            "id"            => $tech->getId(),
            "name"          => $tech->getName(),
            "class_name"    => $tech->getClassName(),
            "order_index"   => $tech->getOrderIndex(),
        );
        if (null === $tech->getId()) {
            unset($data["id"]);
            $data["created"] = time();
            $tech->setId($this->getDbTable()->insert($data));
        }
        else {
            $data["modified"] = time();
            $this->getDbTable()->update($data, array("id = ?" => $data["id"]));
        }
        return $this;
    }

    public function fetchAll() {
        $resultSet = $this->getDbTable()
            ->select()
            ->order(array("order_index", "name"))
            ->query()
            ->fetchAll();
        $entries = array();
        foreach ($resultSet as $row) {
            $entry = new Default_Model_Technology();
            $entry->setId($row["id"])
                ->setName($row["name"])
                ->setClassName($row["class_name"])
                ->setOrderIndex($row["order_index"]);
            $entries[] = $entry;
        }
        return $entries;
    }
}

in application/models/DbTable/Technologies.php:

<?php
class Default_Model_DbTable_Technologies extends Zend_Db_Table_Abstract {
    /**
     * table name
     * @var strings
     */
    protected $_name = "technologies";
}

tests/application/ControllerTestCase.php:

<?php
class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {

    /**
     * @var Zend_Application
     */
    protected $_application;

    /**
     * Prepares the environment before running a test.
     */
    public function setUp() {
        $this->bootstrap = array($this, "appBootstrap" );
        parent::setUp();
    }

    public function appBootstrap() {
        $this->_application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . "/configs/application.ini" );
        $this->_application->bootstrap();
    }
}

Oh, and the tests/application/bootstrap.php file for unit testing:

<?php
error_reporting(E_ALL | E_STRICT);
date_default_timezone_set("Europe/Vienna");

defined("APPLICATION_PATH")
    || define("APPLICATION_PATH", realpath(dirname(__FILE__) . "/../../application"));
defined("APPLICATION_ENV")
    || define("APPLICATION_ENV", (getenv("APPLICATION_ENV") ? getenv("APPLICATION_ENV") : "testing"));
set_include_path(implode(PATH_SEPARATOR, array(
    get_include_path(),
    realpath(APPLICATION_PATH . "/../library"),
    "/usr/local/share/pear",
)));
require_once 'Zend/Loader/Autoloader.php';
require_once 'Zend/Application/Module/Autoloader.php';
/**
 * @var Zend_Application_Module_Autoloader
 */
$autoloader = new Zend_Application_Module_Autoloader(array(
    "namespace" => "Default",
    "basePath" => APPLICATION_PATH
));
require_once 'ControllerTestCase.php';

@Constantin Ehrenstein

In class ModelTechnologyMapperTest (tests/TechnologyMapperTest.php). Missing, parent::setUp().


<?php
class ModelTechnologyMapperTest extends ControllerTestCase
{

    /**
     * @var Default_Model_TechnologyMapper
     */
    protected $_mapper;

    public function setUp() {
        parent::setUp(); // add
        $this->_mapper = new Default_Model_TechnologyMapper();
    }

    public function tearDown() {
        $this->_mapper->getDbTable()
            ->delete(array("order_index = ?" => -101));
        $this->_mapper->getDbTable()
            ->delete(array("order_index = ?" => -100));
    }

    public function testDbTableProperty() {
        $this->assertClassHasAttribute("_dbTable", "Default_Model_TechnologyMapper");
    }
}