PHP - 用于拦截方法调用的runkit的替代方法

时间:2011-05-27 15:26:36

标签: php reflection runkit

我有一些非常不友好的测试代码(至少可以说是我需要测试的)。不幸的是,重构不是一种选择。我必须按原样测试代码,而不必更改代码。

要做到这一点,我正在考虑拦截函数调用并动态更改它们的作用,以便我可以运行我的测试,因为我需要一些函数和方法来返回已知值,我需要其他人发出请求,连接到数据库等,停止这样做并返回我需要它们返回的内容。有没有办法在没有runkit_method_redefine()的情况下做到这一点,最好不是“实验”并仍然保持?也许是runkit的替代品?也许是更好的方式?

编辑:如果我需要这个功能,将使用PHPUnit的测试双打和PHP 5.3.2的功能来使私有方法可访问。

2 个答案:

答案 0 :(得分:15)

  

注意: the Test-Helper extension is superseded https://github.com/krakjoe/uopz

PHPUnit的Test Helper扩展(PECL)允许redefiniton/intercepting/stubbing/mocking of hardcoded dependencies使用您自己的实现:

protected function setUp()
{
    $this->getMock(
      'Bar',                    /* name of class to mock     */
      array('doSomethingElse'), /* list of methods to mock   */
      array(),                  /* constructor arguments     */
      'BarMock'                 /* name for mocked class     */
    );

    set_new_overload(array($this, 'newCallback'));
}

它还允许拦截exit语句和实例创建:

对于存根和模拟方法,您只需使用PHPUnit的常规模拟框架。见

您还可以将Mockery与PHPUnit一起使用:

另一种选择是使用http://antecedent.github.io/patchwork

  

Patchwork是一个PHP库,可以在运行时重新定义用户定义的函数和方法,在纯PHP 5.3代码中松散地复制功能runkit_function_redefine,除此之外,还可以替换静态和私有方法与测试双打。

答案 1 :(得分:2)

runkit扩展是满足您需求的完美解决方案。多年的个人经验证明了这一点,并在互联网上不同作者撰写的许多演讲和文章中进行了描述。

我可以向您保证runkit_method_redefine函数以及整个runkit扩展不再是实验性的(在php.net上托管的文档已经过时)。 可以在http://github.com/zenovich/runkit

上找到最新的runkit扩展

此致 德米特里·泽诺维奇