2013-05-28 36 views
0

免責聲明:是的,我已經閱讀了FAQ,並在Stackoverflow的邊界內考慮了這樣一個問題。不,我不知道如何正確命名它。 :(如何進行單元測試並重構此PHP函數?

我的問題很簡單:如何單元測試下面的方法和我應該做的重構,使之可測試我再說一遍:我不想要求DB和Yii應用實例左右浮動測試這個功能。

public function getOrderCountGroupedByStatus() 
{ 
    $arr = $this->db->createCommand() 
     ->select('COUNT(status) AS count_status, status') 
     ->from('order_item') 
     ->group('status') 
     ->order('status') 
     ->queryAll(); 

    $orderItemsCountByStatus = array(); 
    foreach($arr as $os) 
     $orderItemsCountByStatus[(int)$os['status']] = $os['count_status']; 

    return $orderItemsCountByStatus; 
} 

這是遺留代碼通過手動測試整個應用程序進行有效性檢查。

它是基於Yii framework PHP應用程序。

$this->db是一個CDbConnection對象。 $this->db->createCommand()返回一個CDbCommand對象。

CDbCommand.queryAll()返回在每次迭代時發出數組array('status' => (string), 'count_status' => (int))的可迭代對象。

這種方法顯然有兩個責任:第一個從外部數據源獲取原始數據,第二個將原始數據重新排列到最終結果。我知道它應該以某種方式分開。

  1. 數據庫接口使用工廠方法,該方法返回帶有可鏈式方法的對象。這是嘲弄的噩夢。我開始爲CDbCommand和創建CDbConnection的CDbConnection編寫手動僞造代碼,但是我已經編寫了很多代碼,可能需要它自己的單元測試。我完全不理解我應該如何嘲笑對數據庫的請求。
  2. 這段代碼只是一個例子。我有很多類似的方法,但他們中的很多人不是一次調用數據庫,而是多次調用數據庫,所以「獲取原始數據,重新格式化」可能不是這裏的模式,但我不確定。

最後:我正在測試在這裏受相關PHPUnit的測試方法的名稱描述:

public function CanFindNumberOfOrdersGroupedByStatus() 
爲什麼我在這裏停留

主要的原因是什麼,我測試基本上是是否SUT能成功從持久性存儲獲得一些統計數據,就這些了。與數據庫的所有交互都是實現細節,但在我使用的遺留代碼中,它是連接持久性存儲的唯一方式(使用上面的CDbCommand/CDbConnection組合),而這個持久性存儲是MySQL數據庫。

我想知道我是否需要實現CDbConnection的完整後端,它將使用內存中的燈具而不是真正的數據庫來正確地對這些方法進行單元測試。

是的,防止可能的問題,項目政策禁止在Yii框架中內置的ActiveRecords的使用。

+1

設置一個單獨的測試數據庫,並簡單地測試已知結果? –

+0

@IvoRenkema男人,我在這裏談論'單位'測試。整個問題是**而不是**使用真正的數據庫,否則每個人都知道如何測試這樣的功能。 – hijarian

回答

-1

你不需要編寫太多的代碼來測試它。 Yii擁有出色的測試框架,包括數據庫測試和數據庫夾具功能,將完美覆蓋這一傳統功能。

爲了您閱讀:

Testing in Yii(見章節對燈具內)

一般來說,你會到底是什麼了做是:

  1. 設置測試配置和測試引導文件規定在指南中(默認示例應用程序將包含示例測試配置/引導程序設置)。
  2. 用模式創建測試數據庫並指向您的測試配置。
  3. 撰寫一個延伸CDbTestCase的課程。這只是您的普通PHPUnit測試,Yii的特殊附加功能使測試更容易。如果您對PHPUnit不熟悉,請參閱the docs
  4. 根據Yii指南爲您的測試數據庫編寫一些燈具。這可確保測試數據庫的測試數據。
  5. 編寫按原樣調用Order類的函數並像在普通單元測試中一樣聲明結果的測試。 (此代碼單元測試CDbTestCase子類的內部):

    $這 - >的assertEquals( 陣列(1 => 2,2 => 5), 訂單::模型() - > getOrderCountGroupedByStatus() );

+0

我已經回答了一位評論者,對你的回答同樣如此:我既不需要也不想提升整個MySQL實例,並實例化Yii應用程序來測試這個函數。我想要**單元**測試,而不是集成測試。謝謝,我完全知道如何設置與Yii的數據庫測試,在那裏,做到了。 – hijarian