【问题标题】:how to change current-time for unit testing date functions in php如何在 php 中更改单元测试日期函数的当前时间
【发布时间】:2011-05-12 09:52:36
【问题描述】:

如何在 PHP 中更改当前时间(即 time() 的输出)以进行单元测试 date-manipulation-class?

【问题讨论】:

  • 你能显示一些代码吗?在我看来,如果您需要覆盖 time() 进行单元测试,可能测试或代码有问题。
  • 该类操作当前日期。我只想检查所有日期中的所有方法是否正确。
  • 为什么不直接操作作为参数传递的任何日期?这样你会得到更好的覆盖范围。
  • Carbon::setTestNow(); 看起来很有帮助:carbon.nesbot.com/docs/#api-testing

标签: php unit-testing apache phpunit


【解决方案1】:

如果您使用 PHP 5.3 命名空间,我最近提出了一个非常棒的解决方案。您可以在当前命名空间内实现一个新的 time() 函数,并创建一个共享资源,您可以在其中设置测试中的返回值。然后对 time() 的任何不合格调用都将使用您的新函数。

为了进一步阅读,我在blog中详细描述了它

【讨论】:

  • 我最近实现了库 php-mock,它使用该语言特性来模拟非确定性 PHP 函数,例如 time()
【解决方案2】:

听起来您需要从日期操作类中删除 time() 的依赖项

【讨论】:

  • 所以,我应该改变类的逻辑只是为了测试?
  • @happytoad - 不,您只需要将日期操作类中对 time() 的调用替换为您可以控制的内容。例如,您可以将时间值作为参数传递给您正在测试的函数,或者您可以将其传递给日期类的构造函数。
  • 所以没有办法改变时间。奇怪的是,像更改当前时间这样简单的事情不能用于测试。真可惜。谢谢。
【解决方案3】:

我的猜测是你正在为你的依赖而苦苦挣扎。看起来您在类中使用 time() 函数,而在进行单元测试时,您希望确保控制为您提供时间的方法/类的输出。我会说创建一个 Time 类,为您提供时间并将其模拟到您的单元测试中。

【讨论】:

    【解决方案4】:

    您可以考虑基于接口的继承模型:

    interface iClock
    {
        public function getTime();
    
    }
    
    class SystemClock implements iClock
    {
        public function getTime()
        {
            return time();
        }
    }
    
    class FakeClock implements iClock
    {
        private $time;
    
        function __construct($time)
        {
            $this->time = $time;
        }
    
        public function getTime()
        {
            return $this->time;
        }
    
        // you could have more functions to advance the time, etc.
    }
    

    需要使用当前时间的您自己的类将采用iClock 接口类型的构造函数参数。

    class YourOwnClass
    {
        private $clock;
    
        function __construct(iClock $clock)
        {
            $this->clock = $clock;
        }
    
        function someFunction()
        {
            $now = $this->clock->getTime();
    
            // whatever
            return $now;
        }
    }
    

    然后您只需注入所需的时钟类型,具体取决于您是否在单元测试中:

    $realWorldInstance = new YourOwnClass(new SystemClock());   
    echo $realWorldInstance->someFunction();
    
    $unitTestInstance = new YourOwnClass(new FakeClock(1234));
    echo $unitTestInstance->someFunction();
    

    顺便说一句 - 我也经常在 .NET 中使用这种模式。它还内置在Noda Time 提供的IClock 接口中。我看不出为什么这种模式在 PHP 中不起作用。您可以选择返回 DateTime 而不仅仅是整数时间戳,但以上是使用该模式所需的最小值。

    【讨论】:

      猜你喜欢
      • 2015-08-28
      • 2021-11-09
      • 1970-01-01
      • 2017-12-29
      • 2011-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-05
      相关资源
      最近更新 更多