单元测试包含DateTime("now")的函数

EdL*_*EdL 3 php datetime phpunit unit-testing codeigniter

我有一个类似这样的功能:

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);
}
Run Code Online (Sandbox Code Playgroud)

它返回当前周的数据集,基本上从具有上周一和本周日之间的日期的表中选择记录.

我希望能够对此进行单元测试,但在启动DateTime构造函数时我不知道如何执行此操作.这将是本周但实际上用于测试目的我只想在测试数据集中有一周的数据,所以我真的希望测试DateTime每次都是相同的日期.

基本上我怎么能每次将DateTime("now")设置为相同的模拟日期.我正在使用PHP,Codeigniter和PHPUnit/CIUnit(隐含在标签中).

STL*_*key 6

您可以将$date_start变量传递给函数,当您在测试中调用它时,每次都是相同的

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

您的方法签名将更改为:

    class myclass {
      public function getSomeInfo($id, $date_start = new DateTime()){...}
    }
Run Code Online (Sandbox Code Playgroud)


gon*_*lez 5

有(至少)两种方法:

  1. 委托将当前时间带入另一个类的操作。将TimeProvider或类似的类作为外部依赖项传递给该方法,或者使用ServiceContainer或任何您喜欢的方式传递给该方法,并在测试中使用模拟或什至按照您想要的方式使用的TimeProvider子类。

  2. 使用受保护的方法获取当前时间并模拟(通过创建局部模拟)被测对象。

我通常更喜欢第一种方式。