【发布时间】:2013-02-23 21:22:47
【问题描述】:
这是我要测试的类的高度简化版本:
class SimpleORM {
private $table, $pdo;
public function __construct(PDO $pdo, $table) {
$this->pdo = $pdo;
$this->table = $table;
}
public function findById($id) {
$stmt = $this->pdo->prepare('SELECT * FROM ' . $this->table . ' WHERE ' . $this->primaryKey() . ' = :id');
$stmt->execute(array(':id' => $id);
return $stmt->fetch(PDO::FETCH_OBJ);
}
}
那么,我的问题是,我该如何为这门课编写测试?
我可以像这样模拟 PDO:
public function testFindById() {
$pdo = $this->getMock('PDO', array('prepare'));
$stmt = $this->getMock('PDOStatement', array('execute', 'fetch'));
$stmt->expects($this->once())->method('execute')->with($this->equalTo(array(':id' => 123)));
$stmt->expects($this->once())->method('fetch');
$pdo->expects($this->once())->method('prepare')
->with($this->equalTo('SELECT * FROM test WHERE id => :id'))
->will($this->returnValue($stmt));
$mapper = new SimpleOrm($pdo, 'test');
$mapper->findById(123);
}
这种方法的问题在于,将findById() 方法的内部工作暴露给测试,如果他们改变了测试将失败,即使该方法可能已经被重构以正常工作。
为了使findById() 方法成功,它必须调用pdo::prepare(),它必须返回一个具有execute() 和fetch() 方法的对象(正如pdostatement 目前所做的那样)。但是,如何在不将方法的实现暴露给测试的情况下进行测试呢?
【问题讨论】: