2013-03-08 27 views
2

這裏的類我試圖測試的一個高度簡化的版本:PHPUnit的 - 懲戒數據庫功能

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()它必須返回一個具有​​和fetch()方法(如PDOStatement對象確實此刻)的對象。但是,如何在不向測試公開方法的實現的情況下對此進行測試?

回答

0

我會離開代碼,並預先填充可測試數據的數據庫。這樣你就不需要僞造PDO,你仍然可以獲得功能。

+1

這當然會導致一個不太脆弱的測試,但這意味着測試PDO以及應用程序代碼,這不是一個真正的單元測試,因爲被測試的代碼不是孤立的。這就是說,這絕對是比嘲笑PDO更好的解決方案。 – 2013-03-11 10:01:28