robier / mock-global-php-functions
模拟全局命名空间中存在的任何函数
v1.0.1
2023-01-01 23:17 UTC
Requires
- php: >=7.3
Requires (Dev)
- phpunit/phpunit: ^9
This package is auto-updated.
Last update: 2024-08-30 01:32:29 UTC
README
模拟全局PHP函数
此库允许您模拟任何全局PHP函数以返回预定义的值。
在看到Symfony的ClockMock组件后,我创建了此库,该组件用于模拟与时间相关的PHP原生函数。我对如何模拟任何PHP全局函数感到好奇,因此创建了此小型库。
这是通过PHP的命名空间回退策略实现的。
如果存在命名空间函数[……]不存在,PHP将回退到全局函数[……]。
库使用所述功能动态创建命名空间函数。为了使此库正常工作,您正在测试的代码应在非全局命名空间上下文中,并调用未指定名称的函数。例如
namespace foo; $time = time(); // This call can be mocked, a call to \time() can't.
已知限制
- 只有命名空间上下文中的未指定名称的函数调用可以模拟。例如,在命名空间
foo
中对time()
的调用是可模拟的,而对\time()
的调用则不是。 - 必须在测试类中对未指定名称的函数的第一个调用之前定义模拟。这在问题编号68541中有记录。在大多数情况下,您可以忽略此限制,因为您只需要在测试之前定义模拟。还建议您将测试作为独立进程运行。
API
目前有2个模拟对象可供开发者使用
MockFunction
- 使用您自己的匿名函数模拟任何给定函数FreezeClock
- 模拟与时间/休眠/日期相关的函数,以便它们保持同步
MockFunction
可以模拟全局命名空间中任何函数的对象。只要不调用该模拟的魔法方法__destruct
,或者通过disable
方法手动禁用,模拟就是活动的。这样,在编写测试时,您不需要手动关闭模拟,因为一旦当前作用域存在,模拟就会禁用,并且您可以有一个干净的开始。
注意:在创建模拟时,请使用静态回调而不是常规回调。这防止它们自动绑定到当前类。
示例
// mock is active as soon it's defined $mock = new MockFunction('app', 'rand', static function(){ return 5; }); namespace app { // some logic $randomNumber = rand(); // random number will be always 5 // some logic }
模拟sleep函数的示例
$mock = new MockFunction('app', 'sleep', static function(){ return 0; }); namespace app { // some logic sleep(100); // sleep will not wait for 100 seconds as function is mocked // some logic }
FreezeClock
可以在给定命名空间中冻结时间的手动对象。
方便的工厂方法
atZero
- 停止时间在时间戳0atTime
- 停止在提供的时间atMicrotime
- 停止在提供的微时间atNow
- 停止在当前时间
受影响的函数
date
- 返回冻结格式的时间time
- 返回冻结时间microtime
- 返回冻结微时间sleep
- 增加冻结时间,并且它不像常规sleep函数那样阻塞usleep
- 增加冻结时间,并且它不像常规usleep函数那样阻塞
use Robier\MockGlobalFunction\FreezeClock; $mock = new FreezeClock::atZero('app/testNamespace'); \app\testNamespace\sleep(15); \app\testNamespace\time(); // would return 15 \app\testNamespace\microtime(true); // would return 15.0 also
测试
首先运行docker/build
构建容器,然后运行docker/run composer run test
以运行所有测试。
贡献
欢迎您贡献!