2

有没有人能够使用Zend_Test_DbAdapter与Zend_Db_Table_Abstract?使用zend测试dbadapter与zend数据库表摘要

我想测试一个我创建的扩展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的测试类片段:

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

结果:

行使模型的方法时

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); 
} 

抛出异常

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 
+0

你可以发布你的模型的代码以及异常的堆栈跟踪是什么? – drew010

+0

我已将代码和痕迹添加到原始文章中。我希望这可以帮助。我应该提及在跟踪中为Category.php和CategoryTest.php列出的行号是错误的,因为我压缩了这篇文章的源代码。 – Nick

+0

在这两种情况下,跟踪都是在Category.php中引用“$ rows = $ this-> fetchAll()”,并且“$ actual = $ this-> fixture-> getMap();”在CategoryTest.php中。 – Nick

回答

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';

+0

感谢您的回应!问题是我试图使用Zend_Test_DbAdapter进行测试。该适配器没有连接到真正的数据库,因此没有表元数据的概念(据我所知)。 – Nick

+0

这是真的,但它延伸自'Zend_Db_Table_Abstract',它在构造的早期执行此检查,所以这就是为什么你会收到错误。在测试中,您仍然需要设置一个您在生产中必须执行的主键。添加主键的定义应该超过错误。 – drew010

+0

正如我之前所说的,Zend_Test_DbAdapter没有元数据的概念,因此没有列可以被设置为主键。最后,我认为你回答了我的问题 - 因为Zend_Db_Table_Abstract需要主键,Zend_Test_DbAdapter不能被使用。这是一个耻辱...... – Nick

2

您可以定义这样做对你Zend_Test_DbAdapter实例如下主键ID:

$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与您的实现中的值一起转换。您需要为每个与被测试的课程进行交互的表执行此操作。

+0

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