我正在尝试测试我的一些PHP代码,但是使用模拟对象失败了。我想模拟一个执行curl请求的函数,因为它不应该每次/ test都执行请求。嘲弄卷曲功能本身,有效。要求它用于另一个课程并在那里嘲笑它,就失败了。
以下是文件:
helper.curl.php:
class Helper_Curl {
/*
** __construct($callDomain) - construct new curl helper using set calldomain
*/
public function __construct($callDomain) {
$this->callDomain = $callDomain;
}
/*
** sendPostArrayToApi($Array) - HTTP POST request to server
*/
public function sendPostArrayToApi($Array) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->callDomain);
// [... curl Settings ...]
$return = curl_exec($ch);
curl_close($ch);
return $return;
}
}
class.request.php
require_once('helper.curl.php');
class RequestClass {
function _set($data, $set_type='edit'){
// [... some code ...]
$curl = new Helper_Curl('http://example.com');
$xml = $curl->sendPostArrayToApi($InfoArray);
if($xml == "") {
return false;
}
// [... some more code ...]
}
}
最后测试:
class ClassRequestTest extends PHPUnit_Framework_TestCase {
public function setUp() {
require_once('class.request.php');
}
public function testSetRefund() {
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<response>
<info-id>12345</info-id>
<transmit-id>315</transmit-id>
</response>';
$stubCurl = $this->getMock('Helper_Curl');
$stubCurl->expects($this->once())
->method('sendPostArrayToApi')
->will($this->returnValue($xml));
$this->object->_set($DataArray);
}
protected function tearDown() {
unset($this->object);
}
}
应该模拟Helper_Curl类中的sendPostArrayToApi函数,并返回给定的_set函数的给定xml数据。如何将$ stubCurl附加到$ this-&gt;对象?无论如何可能吗?
感谢您的时间。
答案 0 :(得分:1)
据我所知,你需要在自动加载的同时使用这样的模拟。由于你在cURL帮助器上有一个“硬”依赖(即你的class.request文件中的“require_once”),当它在代码中调用时,PHP只会看到真正的cURL类并将使用它。如果你使用自动加载,那么PHP可以拦截对该类的自动加载的调用并替换模拟。
否则(这可能是一个更好的解决方案),您应该查看某种IoC解决方案,其中对cURL类的依赖不会在您的请求类中进行硬编码(即您不实例化直接在请求类中的cURL对象)。有多种方法可以实现这一目标。 DI或者更具体地说,依赖注入容器是PHP的当前趋势。您可能还想查看Service Locator。有good article by Martin Fowler描述了所有这些模式以及各种利弊。使用这些模式中的任何一种,您都可以更轻松地将测试对象(模拟或存根等)替换为测试中的代码。