模拟PHP函数 - 命名约定

时间:2015-02-26 18:46:09

标签: php unit-testing phpunit mockery

在编写将模拟本机PHP函数的OOP时创建方法名称的最佳实践是什么?

示例:一个对象需要使用file_put_contents(),我想模仿它,所以我认为正确的方法是在类方法中包装file_put_contents()。但是,命名这些方法的好方法是什么?我想也许是 wrap_file_put_contents(),但这样的事情有更好的标准吗?感谢名单!

2 个答案:

答案 0 :(得分:1)

不要重命名它们。那太可怕了。对于您似乎正在尝试测试的功能vfsStream将允许您测试没有击中磁盘,因此进行快速单元测试,因此您可能不需要嘲笑它。

对于其他事情,您可以使用hack来制作该函数的模拟版本,而不会影响您正在测试的代码的易读性,而只是非常可怕。

通过声明一个与要模拟的函数同名的函数,但是在使用它的函数/方法的命名空间中,函数的命名空间版本将优先于PHP版本使用。

File SomeNamespace \ MockHeader.php:

namespace SomeNamespace;

$headersSet = [];

class MockHeader {
    static function load();
}

function header($string, $replace = true, $http_response_code = null) {
    global $headersSet;
    $headersSet[] = [
       'string' => $string,
       'replace' => $replace,
       'http_response_code' => $http_response_code
    ];
}

File SomeNamespace \ TestClass.php:

namespace SomeNamespace;

class TestClass {
    function foo() {
        header("Content-Type: image/jpg");
    }
}

通过在单元测试中调用SomeNamespace \ MockHeader :: load(),将加载头替换函数,并且优先使用PHP提供的\ header函数。

您还可以使用author of that extension所描述的Uopz来以编程方式替换函数,而不是hackily。但是任何一种方法都比重命名事物更好。

答案 1 :(得分:0)

我不确定是否已经找到了一个首选的解决方案,但是我对此感到非常有趣,所以我想我会把这个没有命名空间的版本放到代码cosmos中以达到有趣的目的。

它将优雅地回归到SPL功能,并且可以扩展。如果你想在Std中设置一些默认值,它们可以以最小的努力嵌套。

最后,对get_defined_functions()的某种实例控制可能有意义,我不确定重复调用的开销是多少:

<?php

class Std
{
    public function __call($name, $args)
    {
        $stdFuncs = &get_defined_functions()['internal'];
        if (in_array($name, $stdFuncs))
        {
            return (method_exists($this, $name))
                ? call_user_func_array(array($this, $name), $args)
                : call_user_func_array($name, $args);
        }
        return false;
    }

    public static function __callStatic($name, $args)
    {
        $stdFuncs = &get_defined_functions()['internal'];
        if(in_array($name, $stdFuncs))
        {
            return (method_exists(get_called_class(), $name))
            ? call_user_func_array(array(get_called_class(), $name), $args)
            : call_user_func_array($name, $args);
        }
        return false;
    }
}

class Test extends Std
{
    public static function strlen($string)
    {
        return trim(strlen($string));
    }
}

// Test it
$x = new Test();
echo $x->strlen("test") . PHP_EOL;
echo $x->intval("test") . PHP_EOL;
echo Test::strlen("test") . PHP_EOL;
echo Test::intval("test") . PHP_EOL;