目前我正在测试一个基于值对象生成XML的类,通过HTTP发送XML并将XML响应解析回第二个值对象。我想在这种情况下测试生成的XML和基于给定XML的解析值对象。
该课程如下:
class MyClient
{
public function send(RequestValues $request)
{
$document = $this->generateMessage($request);
$response = $this->request($document);
return $this->parseResponse($response);
}
protected function generateMessage(RequestValues $request)
{
$document = new DomDocument;
// Do stuff with $request
return $document;
}
public function request(DomDocument $document)
{
$client = $this->getHttpClient();
$client->setRawBody($document->saveXml());
// Configure client
return $client->send();
}
public function parseResponse(Response $response)
{
$parameters = new ResponseValues;
$document = new DomDocument;
$document->loadXml($response->getBody());
// Fill in $parameters
return $parameters;
}
}
我想测试两件事:
RequestValues
参数,生成的XML必须类似于$string
ResponseValues
必须等于$object
我现在正在为#1编写测试,但我认为我只能通过回调来实现这一目标。但是,当测试失败时,回调并没有给我提供非常有用的信息。只有这条消息:
声明指定的回调接受DOMDocument Object()失败。
测试如下:
public function testRequestContainsValidXml()
{
$client = $this->getMock('MyClient', array('request'));
$message = '';
$client->expects($this->once())
->method('request')
->with($this->callback(function($object) use ($message) {
return
($object instanceof DomDocument)
&& ($object->saveXml() === $message);
}));
$request = new DirectoryRequest;
$client->send($request);
}
问题是:如何改进测试以便可以进行正常的字符串比较?我很想让phpunit说“字符串X不等于Y”,这极大地简化了调试。
PS。 GitHub上提供了这个类的完整代码。当然,以上示例是简化版本。这是实际的课程:https://github.com/juriansluiman/SlmIdealPayment/blob/master/src/SlmIdealPayment/Client/StandardClient.php#L58
PPS。如果必须更改代码才能对其进行测试,那不是问题。我只想保持公共API不变(即调用ResponseValues send(RequestValues $request)
答案 0 :(得分:0)
你的班级MyClient
表明它是一个门面。要在UnitTests的上下文中测试外观,通常首先需要测试作为该外观的协作者的所有单元。
正如您通常嘲笑协作者 - 而不是正在测试的单元 - 您的测试设置看起来不对,因为您正在嘲笑正在测试的MyClient
单元但不是它的合作者。
例如:
您想测试MyClient::parseResponse()
方法是否返回预期的ResponseValues
对象。因此,你会模仿Response
,因为在这种情况下它是一个合作者。
您可能还想模拟其他协作者(ResponseValues
)但是您不能,因为它是无法注入的隐藏依赖项(您可以通过将工厂注入MyClient
来解决此问题可以控制这种ResponseValues
)的创建。
对于测试MyClient::parseResponse()
这么多:你会通过Response
模拟注入fixture XML,并在返回值上运行你的断言。
对于测试请求是否包含有效XML(testRequestContainsValidXml()
)的情况,我认为不应该以这种复杂的形式完成。听起来你在这里有一个HTTP客户端,你应该只测试它是否有效,并且不关心它是否也适用于XML,因为如果它工作,它也适用于XML。您测试有效XML的原因不是因为您要测试客户端。因此,请将该测试保留在客户端单元测试之外。
字符串的断言btw。是:
$this->assertSame($expected, $actual);
Phpunit会告诉你字符串之间的差异。其他一些程序员/测试人员在比较XML时也应用了一些XML规范化,以便差异更具可读性。如果您的XML没有问题可以处理无关紧要的空白,您可能会发现类似PHP XML how to output nice format的Q& A和相关的问题。
我希望我可以稍微指出你面临的问题,并扩大你对这个问题的看法。我认为你最关心的是批判性地质疑你当前的模拟用法,因为我给出的例子我已经完全减少了提供合作者的嘲弄,而不是做断言。 Asswertions仅在被测单元上完成,此处为示例MyClient
。