【问题标题】:PHPUnit testing database with Zend_Test_PHPUnit_DatabaseTestCase and database adapter issuePHPUnit 测试数据库与 Zend_Test_PHPUnit_DatabaseTestCase 和数据库适配器问题
【发布时间】:2013-08-09 18:33:51
【问题描述】:

我已经实现了来自Database testing with Zend Framework and PHPUnit 的抽象类,它实现了Zend_Test_PHPUnit_DatabaseTestCase,但是我的数据库抽象层使用Zend_Db_Adapter 的方式以及单元测试如何使用它自己的数据库连接createZendDbConnection 存在问题

有问题的代码是:

public function testSaveInsert()
{
    $hostModel = new MyLibrary_Model_Host();
    $hostModel->setName('PHPUnit - Host Test 1')
        ->setDescription('Host Test Description 1');

    $databaseAPI = new MyLibrary_DatabaseAPI();
    $databaseAPI->addHost($hostModel);

    $hosts = $databaseAPI->getHosts();
    Zend_Debug::dump($hosts);

    // get data from the testing database
    $dataSet = new Zend_Test_PHPUnit_Db_DataSet_QueryDataSet($this->getConnection());
    $dataSet->addTable('HOST', "SELECT host.NAME
            , host.DESCRIPTION
        FROM HOST_TABLE host WHERE name like 'PHPUnit -%'");

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

MyLibrary_DatabaseAPI() 类有一个构造函数

$hostDb = Zend_Registry::get('config')->dbConnectionIds->hostDb;
$this->appDb = Zend_Registry::get($hostDb);

addHost 方法使用注册表中设置的数据库连接,获取主机模型属性并将它们转换为要传递给包函数的参数。我在提交的方法调用中有一个标志(业务需求决定了这一点),所以我可以选择何时执行此操作。

Zend_Debug::dumping 的结果中,主机已添加到数据库表中,但是当我运行assertDataSetsMatchXML 测试时,它没有拾取主机已添加并且失败。

我怀疑问题是当我实例化Zend_Test_PHPUnit...($this->getConnection) 时,它使用createZendDbConnection 创建一个新的数据库会话,它不知道前一个会话,因为我没有'提交'addHost它不知道吗?

如果我运行方法调用并提交记录,它将添加到主机表并且测试通过,但我无法使用 createZendDbConnection 回滚结果,因此记录保留在表中,这是我不想要的。本质上,我想要一个无声的测试,进来,测试并且不留下任何足迹。

关于如何解决此问题的任何想法?以这种方式进行测试的基础是数据库具有表的 api,因此我不直接在数据库中进行 CRUD。 PHP 数据库 API 类反映了我可以对数据库 API 进行的调用,因此我想测试这些方法中的每一个。

【问题讨论】:

    标签: php zend-framework phpunit zend-db


    【解决方案1】:

    您应该允许您的类注入它们拥有的依赖项,而不是从注册表中获取它们。这是一种称为“依赖注入”的模式,大约有两种不同的类型:通过构造函数模式或通过 setter 注入。

    这样,您的 DatabaseAPI 将在实例化时接受数据库连接,而不是从“某处”获取一个,并且该数据库连接可以是模拟对象而不是真实对象。

    mock 可以配置为等待某些方法调用,可以检查参数是否正确,甚至可以返回定义的结果。所有这些模拟调用都是测试的一部分。

    最大的好处:模拟只发生在内存中,它们不会像数据库那样影响任何永久存储。这意味着它们比真正的数据库访问要快得多,并且在取消设置或忘记变量后不会留下任何痕迹。

    软件真正需要使用底层硬件的唯一地方是那些必须完成实际工作的类。对您来说幸运的是,您正在使用 Zend 框架的类,您可以认为它们已经过测试,不需要自己再做一遍(除非您怀疑有错误)。

    【讨论】:

    • 这通常是正确的,但我认为问题的重点是使用 Zend Table 抽象进行一些 DB 测试。基于 ZF 1 的应用程序也经常使用注册表,并且众所周知它们很难(有人说不可能)进行测试。部分原因是你在这里写应该改用什么。但是,鉴于问题中的链接,我认为它询问的内容更具体,而不仅仅是 Greenfield TDD 方法的外观。
    • 谢谢你们。 Sven 我已阅读以下文章,发现它解释了您强调的概念。 misko.hevery.com/2008/10/21/…
    猜你喜欢
    • 1970-01-01
    • 2011-10-17
    • 2011-05-08
    • 2015-03-15
    • 1970-01-01
    • 2012-03-20
    • 2020-12-30
    • 2014-11-21
    • 2012-06-02
    相关资源
    最近更新 更多