如何在 phpunit 测试中伪造 DateTime?

How to fake DateTime in a phpunit test?

ss我使用 Symfony 的 KernelTestCase 编写了一个单元测试,并且必须测试一个功能,这只发生在一天中的特定时间(特别早或特别晚)。

所以当我让我的测试运行一个中午当然什么也没有发生。我如何伪造我的系统时间来假装它有不同的时间并触发我的测试用例。

我尝试使用 Symfony 的 ClockMock class 但它不起作用。 https://symfony.com/doc/current/components/phpunit_bridge.html#clock-mocking

这是我的测试代码:

use Symfony\Bridge\PhpUnit\ClockMock;
use \DateTime;

/**
 * testUserAchievedEarlyBirdTrophy
 * @group time-sensitive
 */
public function testUserAchievedEarlyBirdTrophy()
{
    ClockMock::withClockMock(strtotime('2018-11-05 01:00:00'));
    echo (new DateTime())->format('Y-m-d H:m:s');

    $user8Id = $this->user8->getId();
    $progressSaveRequest = new ProgressSaveRequest($user8Id, $this->content_1_1->getId());

    $this->progressService->saveProgress($progressSaveRequest);

    $this->assertTrue($this->loggerCreator->hasDebugThatContains(
        'Early Bird'
    ));
}

echo 给我今天的日期:2019-02-01 16:02:06

我也觉得 ClockMock 更适合用来跳过时间,例如测试缓存而不是 sleep()。

我做错了什么?

监听器配置在我的 phpunit.xml 调用 bin/simple-phpunit 会导致大量安装发生。

我不能使用普通的 phpunit 吗?

还有其他方法可以伪造一天中的时间吗?

在您 post 中包含的 link 之后,第一段说:

The ClockMock class provided by this bridge allows you to mock the PHP's built-in time functions time(), microtime(), sleep() and usleep(). Additionally the function date() is mocked so it uses the mocked time if no timestamp is specified. Other functions with an optional timestamp parameter that defaults to time() will still use the system time instead of the mocked time. (Emphasis added.)

这意味着您对

的调用
echo (new DateTime())->format('Y-m-d H:m:s');

应该给出系统时间,而不是模拟时间。

改为

echo date('Y-m-d H:m:s');

为了匹配ClockMock的要求,得到模拟的时间。

注意:我自己从未使用过 ClockMock,但只要查看文档,这应该是了解这是否能解决您的问题的第一步。