3

我有一個簡單的PHP類,它包裝對數據庫的訪問以檢索用戶並希望對其進行單元測試。目前,我有以下代碼:綁定到實現詳細信息的數據庫單元測試

要測試的類:

class UserTable { 

    protected $tableGateway; 

    public function __construct(\Zend\Db\TableGateway\TableGateway $tableGateway) { 
     $this->tableGateway = $tableGateway; 
    } 

    public function getUserWithId($id) { 
     return $this->tableGateway->select(['id' => $id])->current(); 
    } 
} 

單元測試:

class UserTableTest extends \PHPUnit_Framework_TestCase { 
    public function testGetUserWithIdReturnsCorrectUser() { 
     $user = new User(); 

     $resultSet = new ResultSet(); 
     $resultSet->initialize([$user]); 

     $mockTableGateway = $this->getMock('\Zend\Db\TableGateway\TableGateway', ['select'], [], '', false); 
     $mockTableGateway->expects($this->once())->method('select')->with(['id' => 1])->willReturn($resultSet); 

     $userTable = new UserTable($mockTableGateway); 

     $this->assertEquals($user, $userTable->getUserWithId(1)); 
    } 
} 

不過,現在的單元測試想如果我以後決定改變方式失敗我使用表格網關(例如使用select(['id = ?' => $id])。這將單元測試綁定到應該避免的getUserWithId($id)的實現細節。

防止單元測試取決於實現細節的最佳做法是什麼?是否值得努力建立一個單元測試可以運行的實際測試數據庫(這也將大大減緩測試的執行速度)還是有更好的方法來模擬表格網關?

+1

你可以創建自己的網關對象代碼的經驗,你總是使用,然後這些表測試只與一個網關接口,但是應該改變你只改變你的定製網關,而不是使用那個zend表網關的任何地方 – STLMikey 2014-10-28 17:30:26

+0

這就是我的UsersTable實際上設計的目的。要進一步封裝Zend TableGateway併爲應用程序的其餘部分提供一個接口。那麼,你建議增加另一個抽象層次,它簡單地包裝了TableGateway,不包含邏輯,不需要測試? – 2014-12-01 07:41:10

回答

2

請勿模擬您不擁有的代碼!*對於使用數據庫的類,您必須編寫集成測試。好的是,這會迫使你將DB訪問與其他邏輯分開。

*這是從實際的建議「成長的面向對象的軟件,通過測試指導」一書中,輔以我自己的寫作試驗使用學說的實體管理器

相關問題