PHPUnit测试无法模拟依赖项

3
我将尝试使用PHPunit来模拟一些依赖项,但我的模拟对象似乎无法正常工作。
Logger.php
class Logger
{
    function __construct($log_path)
    {
        // make sure file exists, open file handle
    }
    function write($msg)
    {
        // write message to log 
    }
}

MyCurl.php

class MyCurl
{
    function __construct($url)
    {
        // set my default curl options
    }
    function exec()
    {
        // execute curl request and capture output
    }
}

function_x.php

require_once("Logger.php");
require_once("MyCurl.php");
function function_x($params)
{
    // set some stuff up;
    $LoggerObj = new Logger($filepath);
    $CurlObj   = new MyCurl($url);
    // more stuff
    $LoggerObj->write($CurlObj->exec());
    // do stuff
    return $result;
}

function_x_Test.php

require_once('function_x.php');
class functionXTest extends PHPUnit_Framework_TestCase
{
     public function testCleanRun()
     {

         $MockLogger = $this->getMockBuilder('Logger')->disableOriginalConstructor()->setMethods(array('write', '__destruct'))->getMock();
         $MockLogger->expects($this->any())->method('write')->will($this->returnValue(true));

         $MockCurl   = $this->getMockBuilder('MyCurl')->disableOriginalConstructor()->setMethods(array('exec', '__destruct'))->getMock();
         $MockCurl->expects($this->any())->method('exec')->will($this->returnValue('exec returnz'));

         $result = function_x($params);
         // start assertions with function_x results
    }
}

当我运行我的测试时,它显示我的Logger类正在调用原始构造函数。看起来没有使用模拟类。我假设如果我在测试中声明了模拟,那么对原始类的所有调用都将被模拟,从而消除这些依赖项。显然,我做错了什么。有人可以帮帮我或指点我正确的方向吗?谢谢!

啊,依赖注入。是的,我也想过这个方法,但我觉得修改“生产代码”来使用“测试数据”有点不妥当。然而,它确实非常好用。非常感谢! - sethammons
1个回答

3
Mocking是替换一个对象(参见文档),而不是一个类。
因此,要使用mocks使您的示例工作,您应该注入对象(依赖注入):
function function_x($params, $logger = null, $curl = null)
{
  //Here, you can set logger and curl if they are null.
  // only do this to make sure legacy code works.
  if(!$logger) {
    $logger = new Logger();
  }
  if(!$curl) {
    $curl = new MYCurl();
  }

  //rest of your code
}

而在你的测试中,你调用了

require_once('function_x.php');
class functionXTest extends PHPUnit_Framework_TestCase
{
  public function testCleanRun()
  {

    $MockLogger = $this->getMockBuilder('Logger')->disableOriginalConstructor()->setMethods(array('write', '__destruct'))->getMock();
    $MockLogger->expects($this->any())->method('write')->will($this->returnValue(true));

    $MockCurl   = $this->getMockBuilder('MyCurl')->disableOriginalConstructor()->setMethods(array('exec', '__destruct'))->getMock();
    $MockCurl->expects($this->any())->method('exec')->will($this->returnValue('exec returnz'));

    $result = function_x($params, $MockLogger, $MockCurl);
     // start assertions with function_x results
  }
}

谢谢!依赖注入。在PHP中,这似乎是解决这个问题的事实标准解决方案。 - sethammons

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接