我已经实现了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进行的调用,因此我想测试每种方法。
答案 0 :(得分:1)
您应该允许您的类注入他们拥有的依赖项,而不是从注册表中获取它们。这是一种称为“依赖注入”的模式,它有两种不同的类型:通过构造函数模式注入,或通过setter注入。
这样,您的DatabaseAPI在实例化时会接受数据库连接,而不是从“某处”获取数据库连接,并且该数据库连接可以是模拟对象而不是真实对象。
模拟可以配置为等待某些方法调用,可以检查参数是否正确,甚至可以返回定义的结果。所有这些模拟调用都是测试的一部分。
最大的好处:模拟只发生在内存中,它们不会像数据库那样影响任何永久存储。这意味着它们比真正的数据库访问更快,并且在它们的变量未被设置或遗忘之后它们不会留下任何痕迹。
软件真正需要使用底层硬件的唯一地方是那些必须完成实际工作的类。幸运的是,你正在使用Zend框架的类,你可以认为它们经过测试不需要自己再做(除非你怀疑是错误)。