以下是我拥有的phpspec代码
function it_throws_if_raw_data_xml_is_invalid()
{
$website = $this->buildWebsite("some-deterministic-id", "some-deterministic-name");
$this->convertAdwordsRawData($website, "yesterday", "invalidXML");
$this->shouldThrow(AdwordsResponseNotParseable::class)
->during("convertAdwordsRawData", [$website, "yesterday", "invalid-xml"]);
}
测试失败,但不是因为逻辑错误,而是因为convertAdwordsRawData
从未被调用。我在其中添加了var_dump,但它不会显示,而构造函数的输出会通过。我试图传递字符串而不是$网站,但遇到了类型提示问题。如果我只是在没有断言的情况下调用测试内部的方法,那么它永远不会调用该方法并通过测试,也不会从var_dump输出任何内容。总之,phpspec并没有为我执行这个方法。它上面的一个测试测试相同的公共方法,效果很好。
这里可能出了什么问题?
为了论证起见,考虑该方法执行以下
public function convertAdwordsRawData(Websites $website, string $time, string $rawData): Generator
{
var_dump("Here I am");
throw new AdwordsResponseNotParseable($rawData);
yield from [1,2,3,4,5];
}
更新好的,所以这一切都归结为php如何处理生成器。方法调用将返回一个尚未初始化的迭代器。当我在实际返回的生成器上调用该方法时,PHP将运行所有内容,直到第一次迭代获得第一个收益,并在任何连续迭代中返回收益。
来自php.net网站
当第一次调用生成器函数时返回内部Generator类。此对象实现迭代器接口
$this->convertAdwordsRawData(...)->shouldThrow(...)->duringCurrent();
是解决方案。current()调用来自PHP中Iterator的实现-该方法将在每次迭代中调用
试试看:
function it_throws_if_raw_data_xml_is_invalid(Websites $website)
{
$this->shouldThrow(AdwordsResponseNotParseable::class)
->during("convertAdwordsRawData", [$website, "yesterday", "invalid-xml"]);
}
更多信息:http://www.phpspec.net/en/stable/cookbook/matchers.html#throw-匹配