slope-it/clock-mock

一个用于测试中模拟当前日期和时间的库。

0.4.0 2023-08-21 12:01 UTC

This package is auto-updated.

Last update: 2024-09-18 12:49:22 UTC


README

Slope s.r.l.

Latest Stable Version Total Downloads License

ClockMock 提供了一种方法来模拟 PHP 中 \DateTime(不可变) 对象和相关日期/时间函数所使用的当前时间戳。它需要 uopz 扩展(版本 >= 6.1.1)。

此库仅用于开发和测试。它不旨在提出一个用于生产代码的时钟服务,因为我们认为在测试代码中模拟当前时间时,您不需要这样做。

我们为什么要构建它

以下是深度解释如何以及为什么构建此库的文章: 文章链接

TL;DR

  • 我们正在寻找一种方法来模拟原生的 php 日期和时间函数和类,而无需为此更改生产代码,也无需使用任何第三方库来处理日期/时钟。
  • 为此目的,我们之前使用的是 php-timecop 扩展,但它从未实现对 PHP 7.4 及以上版本的兼容。

安装

您可以使用 Composer 安装此库。运行以下命令以从 Packagist 安装最新版本

composer require --dev slope-it/clock-mock

请注意,由于这不是面向生产的工具,因此它仅应在开发过程中使用(--dev 标志)。

模拟的函数/方法

  • date()
  • date_create()
  • date_create_from_format()
  • date_create_immutable()
  • date_create_immutable_from_format()
  • getdate()
  • gettimeofday()
  • gmdate()
  • gmmktime()
  • gmstrftime()(从 PHP 8.1 开始已弃用)
  • idate()
  • localtime()
  • microtime()
  • mktime()
  • strftime()(从 PHP 8.1 开始已弃用)
  • strtotime()
  • time()
  • unixtojd()
  • DateTime::__construct
  • DateTime::createFromFormat
  • DateTimeImmutable::__construct
  • DateTimeImmutable::createFromFormat
  • $_SERVER['REQUEST_TIME']
  • $_SERVER['REQUEST_TIME_FLOAT']

使用方法

1. 状态性 API

您可以使用 \DateTime 或 \DateTimeImmutable 调用 ClockMock::freeze。在它之后执行的任何代码都将使用该特定日期和时间作为当前时间戳。完成时调用 ClockMock::reset 以恢复真实、当前的时间。

示例

<?php

use PHPUnit\Framework\TestCase;
use SlopeIt\ClockMock\ClockMock;

class MyTestCase extends TestCase
{
    public function test_something_using_stateful_mocking_api()
    {
        ClockMock::freeze(new \DateTime('1986-06-05'));
        
        // Code executed in here, until ::reset is called, will use the above date and time as "current"
        $nowYmd = date('Y-m-d');
        
        ClockMock::reset();
        
        $this->assertEquals('1986-06-05', $nowYmd);
    }
}

2. 无状态 API

此库还提供了一种基于闭包的 API,该 API 将在特定时间点执行提供的代码。此 API 不需要手动冻结或重置时间,因此在某些情况下可能更不易出错。

示例

<?php

use PHPUnit\Framework\TestCase;
use SlopeIt\ClockMock\ClockMock;

class MyTestCase extends TestCase
{
    public function test_something_using_stateless_mocking_api()
    {
        $nowYmd = ClockMock::executeAtFrozenDateTime(new \DateTime('1986-06-05'), function () {
            // Code executed in here will use the above date and time as "current"
            return date('Y-m-d');
        });
        
        $this->assertEquals('1986-06-05', $nowYmd);
    }
}

如何贡献

  • 您是否在现有代码中发现了任何错误并修复了它们?
  • 您想要贡献新功能或缺少的模拟吗?
  • 您认为文档可以改进吗?

在上述任何情况下,请在此存储库上进行分叉并创建一个拉取请求。我们非常愿意接受贡献!

致谢

  • php-timecop,因为 ClockMock 受其启发。
  • ext-uopz,因为 ClockMock 只是建立在令人惊叹的 uopz 扩展之上的一个非常薄的层,该扩展提供了一种非常方便的方法来在运行时模拟任何函数或方法,包括 php stdlib 的那些。