kenjis/monkey-patch

对 exit()、函数、方法和常量进行 Monkey Patching

v1.0.1 2021-07-14 08:03 UTC

This package is auto-updated.

Last update: 2024-09-25 11:01:35 UTC


README

此包是 ci-phpunit-test 的 Monkey Patching 的独立包。

它提供了四个 Monkey Patcher。

  • ExitPatcher:将 exit() 转换为异常
  • FunctionPatcher:修补函数
  • MethodPatcher:修补用户定义类中的方法
  • ConstantPatcher:更改常量值

目录

需求

  • PHP 7.3 或更高版本

安装

$ composer require --dev kenjis/monkey-patch

用法

注意:错误发生时的行号可能与实际源代码不同。请检查 Monkey Patching 创建的源代码缓存文件。

注意:使用此包会对测试速度产生负面影响。

配置

exit() 转换为异常

此修补器将 exit()die() 语句即时转换为异常。

如果您有一个如下所示的控制器

    public function index()
    {
        $this->output
            ->set_status_header(200)
            ->set_content_type('application/json', 'utf-8')
            ->set_output(json_encode(['foo' => 'bar']))
            ->_display();
        exit();
    }

测试用例可能如下所示

    public function test_index()
    {
        try {
            $this->request('GET', 'welcome/index');
        } catch (ExitException $e) {
            $output = ob_get_clean();
        }
        
        $this->assertContains('{"foo":"bar"}', $output);
    }

修补函数

此修补器允许替换 PHPUnit 无法模拟的全局函数。

但它有一些限制。一些函数不能被替换,可能会引起错误。

因此,默认情况下,我们只能替换 FunctionPatcher 中的十几个预定义函数。

    public function test_index()
    {
        MonkeyPatch::patchFunction('mt_rand', 100, 'Welcome::index');
        
        $output = $this->request('GET', 'welcome/index');
        
        $this->assertContains('100', $output);
    }

MonkeyPatch::patchFunction() 替换 Welcome::index 方法中的 PHP 原生函数 mt_rand(),在测试方法中返回 100

注意:如果您不带第三个参数调用 MonkeyPatch::patchFunction(),则测试方法中所有调用的函数(位于 include_paths 中,不在 exclude_paths 中)都将被替换。例如,库代码中的一个函数可能会被替换,导致意外结果。

更改返回值

您可以使用 PHP 闭包更改修补函数的返回值

        MonkeyPatch::patchFunction(
            'function_exists',
            function ($function) {
                if ($function === 'random_bytes') {
                    return true;
                } elseif ($function === 'openssl_random_pseudo_bytes') {
                    return false;
                } elseif ($function === 'mcrypt_create_iv') {
                    return false;
                } else {
                    return __GO_TO_ORIG__;
                }
            },
            Welcome::class
        );

修补其他函数

如果您想修补其他函数,可以在 MonkeyPatchManager::init() 中的 functions_to_patch 中添加它们。

但存在一些已知的限制

  • 参数通过引用调用的修补函数不起作用。
  • 如果您将非公共回调传递给修补函数,可能会看到可见性错误。例如,您将 [$this, 'method'] 传递给 array_map(),并且类中的 method() 方法不是公共的。

修补用户定义类中的方法

此修补器允许替换用户定义类中的方法。

    public function test_index()
    {
        MonkeyPatch::patchMethod(
            Category_model::class,
            ['get_category_list' => [(object) ['name' => 'Nothing']]]
        );
        
        $output = $this->request('GET', 'welcome/index');
        
        $this->assertContains('Nothing', $output);
    }

MonkeyPatch::patchMethod() 用来替换 Category_model 中的 get_category_list() 方法,在测试方法中会返回 [(object) ['name' => 'Nothing']]

修补常量

这个修补器允许替换常量值。

    public function test_index()
    {
        MonkeyPatch::patchConstant(
            'ENVIRONMENT', 
            'development', 
            Welcome::class . '::index'
        );

        $output = $this->request('GET', 'welcome/index');

        $this->assertContains('development', $output);
    }

MonkeyPatch::patchConstant() 用于替换 Welcome::index 方法中常量 ENVIRONMENT 的返回值。

存在一些已知的限制:

  • 不能修补作为函数参数默认值使用的常量。
  • 不能修补作为常量声明默认值使用的常量。
  • 不能修补作为属性声明默认值使用的常量。
  • 不能修补作为静态变量声明默认值使用的常量。

类参考

请参阅 ci-phpunit-test 文档

许可

本软件包采用 MIT 许可证授权。

请查看 LICENSE