我试图测试我的一些php代码,但由于嘲笑对象而失败。我想模拟一个执行curl请求的函数,因为它不应该每次测试都执行请求。嘲笑旋度函数本身是有效的。为另一个类要求它并在那里嘲笑它是失败的。
以下是文件:
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函数应该被模拟,并返回给定的xml数据供_set函数继续使用。如何将$stubURL附加到$this->对象?无论如何可能吗?
谢谢你抽出时间。
据我所知,您需要将这样的mocking与自动加载结合使用。由于你对cURL助手有一个"硬"依赖(即class.request文件中的"require_one"),当它在代码中调用时,PHP将只看到真正的cURL类并使用它。如果使用自动加载,那么PHP可以拦截自动加载该类的调用并替换mock。
否则(这可能是一个更好的解决方案),您应该考虑某种IoC解决方案,通过这种解决方案,对cURL类的依赖性不会在请求类中硬编码(即,您不会直接在请求类中将cURL对象实例化)。实现这一点有多种方法。DI,或者更具体地说,依赖注入容器是PHP的当前趋势。您可能还需要查看服务定位器。马丁·福勒有一篇很好的文章描述了所有这些模式以及各种利弊。使用这两种模式中的任何一种,您都可以更容易地将测试对象(mock或stub等)替换为被测试的代码。