你好 各位, 我为 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。
我看不到模拟和注入(inject) call
函数的解决方案。我能做些什么?也许我的对象结构不好并且无法测试
我该如何改进这个结构(如果发生这种情况)?
干杯。
最佳答案
由于您正在尝试测试外部 API,因此我首先将您的 file_get_contents()
调用包装在另一个类中,并将其注入(inject)到您的 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());
...
}
}
现在在您的测试中,您可以使用模拟对象作为文件检索器注入(inject)。例如:
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 .
关于PHP 单元测试 : How to test low level functions of an external api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18254410/