如何使用PHPUnit测试模拟方法链

Ase*_*tib 7 php phpunit unit-testing mocking

我正在尝试模拟一个链(嵌套)方法来返回所需的值,这是代码:

public function __construct($db)
{
$this->db = $db;
}

public function getResults()
{
return $this->db->getFinder()->find($this->DBTable);
}
Run Code Online (Sandbox Code Playgroud)

我试过这个模拟,但它不起作用:

$dbMock = $this->createMock(DB::class);
        $dbMock = $dbMock
            ->expects(self::any())
            ->method('getFinder')
            ->method('find')
            ->with('questions')
            ->will($this->returnValue('7'));
Run Code Online (Sandbox Code Playgroud)

任何解决方案如何解决这样的问题?

谢谢 .

小智 8

现在使用Mocking Demeter Chains 和 Fluent Interfaces更简单

简单地

$dbMock = $dbMock
        ->expects(self::any())
        ->method('getFinder->find')
        ->with('questions')
        ->will($this->returnValue('7'));
Run Code Online (Sandbox Code Playgroud)

来自嘲弄文档的另一个例子

$object->foo()->bar()->zebra()->alpha()->selfDestruct();
Run Code Online (Sandbox Code Playgroud)

你想 selfDestruct回来10

$mock = \Mockery::mock('CaptainsConsole');
$mock->shouldReceive('foo->bar->zebra->alpha->selfDestruct')->andReturn(10);
Run Code Online (Sandbox Code Playgroud)


BVe*_*rov 5

链由被依次调用的对象组成。因此,您需要实现一系列模拟。只需以返回模拟对象的方式模拟这些方法即可。

像这样的东西应该有效:

$finderMock = $this->createMock(Finder::class);
$finderMock = $finderMock
    ->expects(self::any)
    ->method('find')
    ->with('questions')
    ->will($this->returnValue('7'));

$dbMock = $this->createMock(DB::class);
$dbMock = $dbMock
    ->expects(self::any())
    ->method('getFinder')
    ->will($this->returnValue($finderMock));
Run Code Online (Sandbox Code Playgroud)

在这篇很酷的博客文章中阅读有关模拟链接的更多信息。

不过,我真的不明白测试链有什么意义。IMO 最好将测试限制为一次测试 1 个模块(功能)或 2 个模块(交互)。