使用zend测试dbadapter和zend db表摘要

时间:2012-10-14 21:20:31

标签: unit-testing zend-framework zend-db zend-db-table zend-test

有没有人能够将Zend_Test_DbAdapter与Zend_Db_Table_Abstract一起使用?

我正在尝试测试我创建的扩展Zend_Db_Table_Abstract的模型,如果我使用Zend_Test_DbAdapter(其他适配器,如mysql或sqlite),我得到一个关于未设置主键的异常。


class Model_Category extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';

    protected $_dependentTables = array('Model_Video');

    public function getMap()
    {
        $map = array();
        $rows = $this->fetchAll();
        foreach($rows as $row)
        {
            $map[$row->id] = $row->name;
        }

        return $map;
    }
}

PHPUnit测试类的片段:

protected function setUp()
{
    $adapter = new Zend_Test_DbAdapter();
    $stmt = Zend_Test_DbStatement::createSelectStatement(array(
        array('id' => 1, 'name' => 'pranks'),
        array('id' => 2, 'name' => 'physical_feats'),
        array('id' => 3, 'name' => 'art'),
        array('id' => 4, 'name' => 'cute'),
        array('id' => 5, 'name' => 'philanthropy')
    ));
    $adapter->appendStatementToStack($stmt);

    $this->fixture = new Model_Category($adapter);
}

在执行模型的方法时会抛出异常:

public function testGetMap()
{
    $expected = array(
        '1' => 'pranks',
        '2' => 'physical_feats',
        '3' => 'art',
        '4' => 'cute',
        '5' => 'philanthropy'
    );
    $actual = $this->fixture->getMap();
    $this->assertEquals($expected, $actual);
}

结果:

Model_CategoryTest::testGetMap()
Zend_Db_Table_Exception: A table must have a primary key, but none was found
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:876
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:969
ZendFramework-1.10.6/library/Zend/Db/Table/Select.php:100
ZendFramework-1.10.6/library/Zend/Db/Table/Select.php:78
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:1005
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:1303
application/models/Category.php:35
tests/unit/application/models/CategoryTest.php:90

强制主键也不起作用:

protected function setUp()
{
    $adapter = new Zend_Test_DbAdapter();
    $stmt = Zend_Test_DbStatement::createSelectStatement(array(
        array('id' => 1, 'name' => 'pranks'),
        array('id' => 2, 'name' => 'physical_feats'),
        array('id' => 3, 'name' => 'art'),
        array('id' => 4, 'name' => 'cute'),
        array('id' => 5, 'name' => 'philanthropy')
    ));
    $adapter->appendStatementToStack($stmt);

    $this->fixture = new Model_Category(array(
        'db' => $adapter,
        'primary' => 'id'
    ));
}

执行相同的单元测试,从上面得到:

Model_CategoryTest::testGetMap()
Zend_Db_Table_Exception: Primary key column(s) (id) are not columns in this table ()
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:888
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:969
ZendFramework-1.10.6/library/Zend/Db/Table/Select.php:100
ZendFramework-1.10.6/library/Zend/Db/Table/Select.php:78
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:1005
ZendFramework-1.10.6/library/Zend/Db/Table/Abstract.php:1303
application/models/Category.php:35
tests/unit/application/models/CategoryTest.php:93

2 个答案:

答案 0 :(得分:2)

您可以在Zend_Test_DbAdapter实例上执行以下操作来定义主键:

$adapter = new Zend_Test_DbAdapter();
$adapter->setDescribeTable('table_name', array('column_name' =>
    array(
        'SCHEMA_NAME' => 'schema_name',
        'TABLE_NAME'  => 'table_name'
        'COLUMN_NAME' => 'column_name',     
        'PRIMARY'     => true
    )
));

然后使用实现中的值转置table_name,column_name和schema_name。您需要为要在测试的类中与之交互的每个表执行此操作。

答案 1 :(得分:0)

您获得异常Zend_Db_Table_Exception: A table must have a primary key, but none was found的原因是因为使用Zend_Db_Table的所有表都必须定义主键。当您使用该表时,由于未在DbTable类中定义主键,Zend_Db会尝试通过检查信息模式中的表的属性来确定表的主键。它看到你的表没有主键而失败。

来自manual

  

如果您未指定主键, Zend_Db_Table_Abstract 会尝试   根据提供的信息发现主键    describeTable() 方法。

     

注意:每个表类都必须知道可以使用哪些列进行寻址   行唯一。如果表中未指定主键列   类定义或表构造函数参数,或在中发现   由** describeTable() 提供的表格元数据,则表格不能   与 Zend_Db_Table 一起使用。

尝试强制主键不起作用,因为看起来您的表没有一个名为id的列,您将其指定为主键。

解决方案是将主键添加到您尝试使用的表中。

在扩展Zend_Db_Table_Abstract的模型类中,您可以使用protected $_primary = 'primary_column';

指定不是ID的主键