假设我有以下界面:
interface MyInterface
{
public function yieldData();
}
我想创建一个这个界面的模拟,例如:
$mocked_instance = Phake::partialMock(MyInterface::class);
模拟yield方法的首选方法是什么?这是我提出的最好的:
Phake::when($mocked_instance)->yieldData()->thenReturn([]);
有没有办法在PHPUnit / Phake中做到这一点,它更接近函数的原始功能(即返回一个Generator)?
答案 0 :(得分:3)
感谢您Oliver Maksimovic的评论,这有助于我找到适合我的解决方案。
我决定在我的基础测试用例上创建以下函数:
/*
* @param array @array
*
* @return \Generator|[]
*/
protected function arrayAsGenerator(array $array)
{
foreach ($array as $item) {
yield $item;
}
}
这允许我执行以下操作:
$mocked_instance = Phake::partialMock(MyInterface::class);
$numbers = [1, 2, 3, 4, 5];
Phake::when($mocked_instance)
->yieldData()
->thenReturn($this->arrayAsGenerator($numbers));
答案 1 :(得分:0)
您可以使用Phony,一个带有first-class support for generators的PHP模拟库:
$handle = mock(MyInterface::class);
$handle->yieldData->generates([1, 2, 3, 4, 5])->returns();
答案 2 :(得分:0)
我仅使用PHPUnit,不想与添加Phake或其他测试框架混为一谈。我发现此问题最有用的解决方案来自本文:
https://www.gpapadop.gr/blog/2017/11/01/mocking-generators-in-phpunit/
但是,我不喜欢本文中语法的选择,而且我认为使用辅助方法generate()
更容易理解代码。在幕后,它仍然像本文中一样使用PHPUnit::returnCallback()
。
这是一个示例类,它带有我需要模拟的Generator方法:
class MockedClass
{
public function generatorFunc() : Generator
{
$values = [1,2,3,4];
foreach($values as $value)
{
yield $value;
}
}
}
这是一个带有generate()
帮助方法的PhpUnit Test类,该方法实现了以上文章中的解决方案:
class ExampleTest extends \PHPUnit\Framework\TestCase
{
// Helper function creates a nicer interface for mocking Generator behavior
protected function generate(array $yield_values)
{
return $this->returnCallback(function() use ($yield_values) {
foreach ($yield_values as $value) {
yield $value;
}
});
}
public function testMockedGeneratorExample()
{
$mockedObj = $this->createMock(MockedClass::class);
$mockedObj->expects($this->once())
->method('generatorFunc')
->will($this->generate([5,6,7,8]));
// Run code that uses MockedClass as dependency
// Make additional assertions as needed...
}
}