3

我已经使用 Zend Framework 和 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 进行的调用,因此我想测试这些方法中的每一个。

4

1 回答 1

1

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

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

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

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

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

于 2013-08-08T07:10:23.177 回答