我正在尝试使用 PHPUnit 对映射器类进行单元测试。 我可以轻松模拟将注入(inject)到映射器类中的 PDO 实例,但我不知道如何模拟 PreparedStatement 类,因为它是由 PDO 类生成的。
在我的例子中,我扩展了 PDO 类,所以我有这个:
public function __construct($dsn, $user, $pass, $driverOptions)
{
//...
parent::__construct($dsn, $user, $pass, $driverOptions);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS,
array('Core_Db_Driver_PDOStatement', array($this)));
}
重点是 Core_Db_Driver_PDOStatement 没有注入(inject)到 PDO 类的构造函数中,它是静态实例化的。即使我这样做:
public function __construct($dsn, $user, $pass, $driverOptions, $stmtClass = 'Core_Db_Driver_PDOStatement')
{
//...
parent::__construct($dsn, $user, $pass, $driverOptions);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS,
array($stmtClass, array($this)));
}
...它仍然是一个静态实例化,因为我无法传递我自己的准备好的语句类的模拟实例。
有什么想法吗?
编辑: 解决方案,改编自 anwser:
/**
* @codeCoverageIgnore
*/
private function getDbStub($result)
{
$STMTstub = $this->getMock('PDOStatement');
$STMTstub->expects($this->any())
->method('fetchAll')
->will($this->returnValue($result));
$PDOstub = $this->getMock('mockPDO');
$PDOstub->expects($this->any())
->method('prepare')
->will($this->returnValue($STMTstub));
return $PDOstub;
}
public function testGetFooById()
{
$arrResult = array( ... );
$PDOstub = $this->getDbStub($arrResult);
}
最佳答案
如果您可以模拟 PDO 类,只需模拟出 pdo 类及其所有依赖项。由于您通过模拟定义输入和输出,因此无需关心语句类或 pdo 类的构造函数。
所以你需要一个返回模拟对象的模拟对象。
这可能看起来有点困惑,但由于您应该只测试被测类的功能,而没有其他任何东西,您几乎可以摆脱数据库连接的所有其他部分。
在这个例子中,你想弄清楚的是:
- 是否调用了 prepare?
- 是否在 prepare 返回时调用了 fetchAll?
- 调用的结果返回了吗?
如果是这样:一切都好。
<?php
class myClass {
public function __construct(ThePDOObject $pdo) {
$this->db = $pdo;
}
public function doStuff() {
$x = $this->db->prepare("...");
return $x->fetchAll();
}
}
class myClassTest extends PHPUnit_Framework_TestCase {
public function testDoStuff() {
$fetchAllMock = $this
->getMockBuilder("stdClass" /* or whatever has a fetchAll */)
->setMethods(array("fetchAll"))
->getMock();
$fetchAllMock
->expects($this->once())->method("fetchAll")
->will($this->returnValue("hello!"));
$mock = $this
->getMockBuilder("ThePDOObject")
->disableOriginalConstructor()
->setMethods(array("prepare"))
->getMock();
$mock
->expects($this->once())
->method("prepare")
->with("...")
->will($this->returnValue($fetchAllMock));
$x = new myClass($mock);
$this->assertSame("hello!", $x->doStuff());
}
}
关于PHPUnit - 如何模拟 PDO 准备好的语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5339178/