2014-02-25 61 views
3

我有一個類似的功能: 單元測試含日期時間(「現在」)的功能

public function getSomeInfo($id){ 
    $date_start=new DateTime(); 
    $day_of_week=$date_start->format("N"); 
    $date_start=$date_start->sub(new DateInterval("P".$day_of_week."D")); 
    $date_end=new $date_start; 
    $date_end=$date_end->add(new DateInterval("P5D")); 
    $date_start=$date_start->format("Y-m-d"); 
    $date_end=$date_end->format("Y-m-d"); 
    $sql="SELECT * FROM `table` 
      WHERE `table`.`id`=$id 
      AND `session`.`date`>'$date_start' 
      AND `session`.`date`<='$date_end'"; 
    $this->db->query($sql); 
} 

它返回這個當前星期的數據集,基本上選擇從表中的記錄與去年之間的日期週一和本週日。

我想能夠單元測試,但我不知道如何做到這一點,當它啓動一個DateTime構造函數。這將是當前的一週,但實際上爲了測試的目的,我只想要測試數據集中的一週數據,所以我真的希望測試日期時間每次都是相同的日期。

基本上我怎麼能設置DateTime(「現在」)每次相同的模擬日期。我使用PHP,Codeigniter和PHPUnit/CIUnit(隱含在標籤中)。

回答

5

你可以在$date_start變量,而不是傳遞給函數,當你在測試中調用它,它會每天同一時間,即

function testMymethod(){ 
    $date_start = new DateTime('2011-01-01'); 
    $class->getSomeInfo($id, $date_start); 
    //assertions 
} 

而且你的方法signiture將變爲:

class myclass { 
     public function getSomeInfo($id, $date_start = new DateTime()){...} 
    } 
+0

啊謝謝,一個例子勝過千言萬語! 這也給我的優勢是能夠使用相同的功能在其他幾周以及:) – EdL

3

有(至少)2種方式爲這樣:

  1. Delega把當前時間變成另一個班的行爲。將TimeProvider或類似的類傳遞給方法,作爲外部依賴項,或者使用ServiceContainer或任何您喜歡的方式,並且在測試中使用模擬或甚至TimeProvider子類,這些子類以您想要的方式運行。

  2. 使用受保護的方法獲取當前時間並對受測主題進行模擬(通過創建部分模擬)。

我通常更喜歡第一種方式。