これは、私がテストしようとしているクラスの非常に単純化されたバージョンです。
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()
メソッドが成功するためには、 andメソッドpdo::prepare()
を持つオブジェクトを返さなければならない呼び出しを呼び出す必要があります(現在 pdo ステートメントが行っているように)。ただし、メソッドの実装をテストに公開せずにこれをテストするにはどうすればよいですか?execute()
fetch()