php - 如何在 php 单元测试中模拟日期?

标签 php phpunit

我是 php 单元测试的新手。如何在下面的函数中模拟日期。目前它正在获取当前日期。但我想将模拟中的日期更改为一个月的第一天。

function changeStartEndDate() {

    if (date('j', strtotime("now")) === '1') {

        $this->startDate = date("Y-n-j", strtotime("first day of previous month"));

        $this->endDate = date("Y-n-j", strtotime("last day of previous month")) . ')';
    } else {

        $this->startDate = date("Y-n-j", strtotime(date("Y-m-01")));
        $this->endDate = date("Y-n-j", strtotime("yesterday"));
    }
}

我试过这样做,但它不起作用。

public function testServicesChangeStartEndDate() {
    $mock = $this->getMockBuilder('CoreFunctions')
        ->setMethods(array('changeStartEndDate'))
        ->getMock();

    $mock->method('changeStartEndDate')
        ->with(date("Y-n-j", strtotime(date("Y-m-01"))));

    $this->assertSame(
        '1',
        $this->core->changeStartEndDate()
    );

}

最佳答案

通过避免副作用,单元测试效果最好。 datestrtotime 都取决于在您的主机系统上定义的外部状态,即当前时间。

解决这个问题的一种方法是使当前时间成为可注入(inject)属性,允许您“卡住”它或将其设置为特定值。

如果您查看 strtotime 的定义它允许设置当前时间:

strtotime ( string $time [, int $now = time() ] ) : int

date 相同:

date ( string $format [, int $timestamp = time() ] ) : string

因此,请始终从您的函数中注入(inject)该值,以将您的代码结果与主机状态分离。

function changeStartEndDate($now) {

    if (date('j', strtotime("now", $now), $now) === '1') {
        ...
        $this->startDate = date("Y-n-j", strtotime(date("Y-m-01", $now), $now));
        $this->endDate = date("Y-n-j", strtotime("yesterday", $now), $now);
    }

你的函数是类的一部分吗?然后,我将 $now 作为构造函数的一部分,并将其默认为 time()。在你的测试用例中,你总是可以注入(inject)一个固定的数字,它总是会返回相同的输出。

class MyClassDealingWithTime {
    private $now;

    public function __construct($now = time()) {
        $this->now = $now;
    }


    private customDate($format) {
        return date($format, $this->now);
    }

    private customStringToTime($timeSring) {
        return strtotime($timeStrimg, $this->now);
    }
}

然后在您的测试用例中将 $now 设置为您需要的值,例如通过

$firstDayOfAMonth = (new DateTime('2017-06-01'))->getTimestamp();
$testInstance = new MyClassDealingWithTime(firstDayOfAMonth);

$actual = $testInstance->publicMethodYouWantTotest();

... 

关于php - 如何在 php 单元测试中模拟日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59304228/

相关文章:

php - PHP,静态变量或私有(private)变量哪个更好?

php - header 已在 PHPStorm 中发送运行单元测试

PHP 单元,使用单元测试测试 laravel 日志消息

php - "Call to undefined method PHPUnit\Framework\TestSuite::sortId()"执行覆盖率测试用例时出错

php - ftp_login 期望参数 1 是资源

php - Symfony AppExtension 未加载

php - 函数覆盖是否需要实例化?

php - 如何使用 php 从 mysql 查询中提取表名?

php - 我来自 phpunit 的assertEquals 说我的字符串不相等,但我已经复制了它们,我认为这是由于行被添加到响应中

php - Symfony 交互式命令测试以 RuntimeException 结束