您好 乡亲, 我为XmlRPC-Api写了一个低级实现,我很难测试通信。
这是我的代码。
abstract class BaseClient
{
protected function call($method, array $params = array())
{
$request = xmlrpc_encode_request($method, $parameters);
$file = file_get_contents($this->getDSN(), false, $context);
$response = xmlrpc_decode($file);
if ($response && xmlrpc_is_fault(array($response))) {
trigger_error("xmlrpc: {$response[faultString]} ({$response[faultCode]})");
}
return $response;
}
}
Client extends BaseClient
{
public function testCall($msg)
{
return $this->call('testMethid', array($msg));
}
}
这是我的测试。
ClientTest extends PHPUnit_FrameWork_TestCase
{
public function testTestCall()
{
$c = new Client();
$resp = $c->testCall('Hello World');
$this->assertEquals('Hello World', $resp);
}
}
此测试每次都会崩溃,因为它无法访问测试环境中的api。
我看不到模拟和注入call
函数的解决方案。我能做什么?也许我的对象结构很糟糕,无法测试
以及如何改进这种结构(如果发生这种情况)?
干杯。
答案 0 :(得分:2)
由于您正在尝试测试外部API,我首先将您的file_get_contents()
调用包装在另一个类中并将其注入BaseClient。在最简单的形式中,它可能看起来像这样:
class RemoteFileRetriever
{
public function retrieveFileContents($url)
{
// Do some work to create $context
...
// Now grab the file contents
$contents = file_get_contents($url, false, $context);
return $contents;
}
}
abstract class BaseClient
{
private $fileRetriever;
public function __construct(RemoteFileRetriever $fileRetriever)
{
$this->fileRetriever = $fileRetriever;
}
protected function call($method, array $params = array())
{
...
$file = $this->fileRetriever->retrieveFileContents($this->getDSN());
...
}
}
现在,在测试中,您可以使用模拟对象作为文件检索器进行注入。 E.g:
class ClientTest extends PHPUnit_FrameWork_TestCase
{
public function testTestCall()
{
$mockRetriever = new MockRemoteFileRetriever();
$c = new Client($mockRetriever);
$resp = $c->testCall('Hello World');
$this->assertEquals('Hello World', $resp);
}
}
PHPUnit实际上有一些用于模拟的内置帮助器。请参阅PHPUnit's Mock Objects。
答案 1 :(得分:0)
您不想模拟call
函数。
如果您无法设置虚假服务,那么您想要使用PHP命名空间模拟PHP功能(必须拥有PHP 5.3)。然后,您可以为调用方法中调用的内部php函数创建模拟。
http://www.schmengler-se.de/-php-mocking-built-in-functions-like-time-in-unit-tests
如果您无法做到这一点,那么测试可能会非常困难。你能创建一个可以用来测试的假api吗?请记住,您实际上并没有测试api的方法,而是试图确保您的代码向api发出请求并以您想要的方式处理响应。
通常,假设第三方代码已经过测试并且运行正常。