gpt4 book ai didi

php - TDD - 不能模拟的依赖

转载 作者:行者123 更新时间:2023-11-28 19:41:25 24 4
gpt4 key购买 nike

假设我有一个类:

class XMLSerializer {
public function serialize($object) {
$document = new DomDocument();
$root = $document->createElement('object');
$document->appendChild($root);

foreach ($object as $key => $value) {
$root->appendChild($document->createElement($key, $value);
}

return $document->saveXML();
}

public function unserialze($xml) {
$document = new DomDocument();
$document->loadXML($xml);

$root = $document->getElementsByTagName('root')->item(0);

$object = new stdclass;
for ($i = 0; $i < $root->childNodes->length; $i++) {
$element = $root->childNodes->item($i);
$tagName = $element->tagName;
$object->$tagName = $element->nodeValue();
}

return $object;
}

}

我如何单独测试它?在测试这个类的时候,我也在测试 DomDocument 类

我可以传入文档对象:

class XMLSerializer {
private $document;

public function __construct(\DomDocument $document) {
$this->document = $document;
}

public function serialize($object) {
$root = $this->document->createElement('object');
$this->document->appendChild($root);

foreach ($object as $key => $value) {
$root->appendChild($this->document->createElement($key, $value);
}

return $this->document->saveXML();
}

public function unserialze($xml) {
$this->document->loadXML($xml);

$root = $this->document->getElementsByTagName('root')->item(0);

$object = new stdclass;
for ($i = 0; $i < $root->childNodes->length; $i++) {
$element = $root->childNodes->item($i);
$tagName = $element->tagName;
$object->$tagName = $element->nodeValue();
}

return $object;
}

}

这似乎解决了问题,但是,现在我的测试实际上没有做任何事情。我需要制作一个模拟 DomDocument 返回我在测试中测试的 XML:

$object = new stdclass;
$object->foo = 'bar';

$mockDocument = $this->getMock('document')
->expects($this->once())
->method('saveXML')
->will(returnValue('<?xml verison="1.0"?><root><foo>bar</foo></root>'));

$serializer = new XMLSerializer($mockDocument);

$serializer->serialize($object);

其中有几个问题:

  1. 我实际上根本没有测试该方法,我只是检查该方法是否返回了 $document->saveXML()
  2. 的结果
  3. 测试知道方法的实现(它使用 domdocument 生成 xml)
  4. 如果类被重写为使用 simplexml 或其他 xml 库,测试将失败,即使它可能产生正确的结果

那么我可以单独测试这段代码吗?看起来我不能..是否有这种类型的依赖项的名称不能被模拟,因为它的行为本质上是被测试方法所必需的?

最佳答案

这是一个关于 TDD 的问题。 TDD意味着先写测试。

我无法想象在编写实际实现之前从模拟 DOMElement::createElement 的测试开始。您很自然地从一个对象和预期的 xml 开始。

此外,我不会将 DOMElement 称为依赖项。这是您实现的私有(private)细节。您永远不会将 DOMElement 的不同实现传递给 XMLSerializer 的构造函数,因此无需在构造函数中公开它。

测试也应该作为文档。使用对象和预期 xml 的简单测试将是可读的。每个人都将能够阅读它并确定您的类(class)在做什么。将此与使用模拟的 50 行测试进行比较(PhpUnit 模拟非常冗长)。

编辑:这是一篇关于它的好论文 http://www.jmock.org/oopsla2004.pdf .简而言之,它指出除非您使用测试来驱动您的设计(寻找接口(interface)),否则使用模拟毫无意义。

还有一个很好的规则

Only Mock Types You Own

(在论文中提到)可以应用于您的示例。

关于php - TDD - 不能模拟的依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31915762/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com