【问题标题】:using zend test dbadapter with zend db table abstract将 zend test dbadapter 与 zend db table abstract 一起使用
【发布时间】:2012-10-14 21:20:31
【问题描述】:

有没有人能够将 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

【问题讨论】:

  • 您能否发布您的模型的代码以及异常的堆栈跟踪是什么?
  • 我已在我的原始帖子中添加了代码和 strack 跟踪。我希望这会有所帮助。我应该提一下,跟踪中为 Category.php 和 CategoryTest.php 列出的行号是错误的,因为我已经压缩了这篇文章的源代码。
  • 在这两种情况下,跟踪都引用 Category.php 中的“$rows = $this->fetchAll()”和“$actual = $this->fixture->getMap();”在 CategoryTest.php 中。

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


【解决方案1】:

您可以通过在 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 转换为您的实现中的值。您需要对您在被测类中与之交互的每个表执行此操作。

【讨论】:

  • 这解决了部分问题,但暴露了一个新的相关问题。当 Zend_Db_Adapter_Abstract 的 fetchPairs() 方法被调用时,$row[0] 和 $row[1] 不存在。这是因为 $stmt->fetch(Zend_Db::FETCH_NUM) 仍然返回关联数组,而不是数值数组。
【解决方案2】:

您收到异常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 的主键

【讨论】:

  • 感谢您的回复!问题是我正在尝试使用 Zend_Test_DbAdapter 进行测试。该适配器没有连接到真实的数据库,因此没有表元数据的概念(据我所知)。
  • 这是真的,但它从 Zend_Db_Table_Abstract 扩展而来,它在构造的早期就执行了此检查,这就是您收到错误的原因。它测试,你仍然需要设置一个主键,无论如何你都必须在生产中做。添加主键的定义应该可以克服错误。
  • 正如我之前所说的 Zend_Test_DbAdapter 没有元数据的概念,因此不能将任何列设置为主键。最后我想你回答了我的问题——因为 Zend_Db_Table_Abstract 需要一个主键,所以 Zend_Test_DbAdapter 不能使用。真可惜……
  • 看起来如果你在 Category 模型中添加了一个虚拟的 protected $_primary = 'id';,错误应该会消失。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多