嘲弄:测试具有不同返回值的链式方法调用(此处:Symfony ProcessBuilder)
Posted
技术标签:
【中文标题】嘲弄:测试具有不同返回值的链式方法调用(此处:Symfony ProcessBuilder)【英文标题】:Mockery: Testing chained method calls with different return values (here: Symfony ProcessBuilder) 【发布时间】:2016-07-18 16:24:46 【问题描述】:我正在尝试使用 Symfony 的 ProcessBuilder 测试创建 2+ Process 对象(另见 API docs)的方法,并且在尝试返回不同的模拟进程对象时遇到了问题。事实上,我有点不确定Mockery 是否能做到这一点。
Mockery的andReturn()
中是否可以根据对象的调用链(包括参数)来选择值?
理想情况下,我正在寻找这样的东西:
<?php
$processBuilderMock
->shouldReceive('setPrefix("test")->add("-f")->getProcess')
->andReturn($testProcess);
完整示例:
如果文件不存在,以下代码将创建一个文件 /tmp/dummy
。它为此使用了test -f /tmp/dummy
和touch /tmp/dummy
这两个命令(我知道这是一个愚蠢的例子)。
<?php
class Toggler
public function toggleFile(ProcessBuilder $builder)
$testProcess = $builder
->setPrefix('test')->setArguments(array('-f', '/tmp/dummy'))
->getProcess();
$testProcess->run();
if (!$testProcess->isSuccessful()) // (a)
$touchProcess = $builder
->setPrefix('touch')->setArguments(array('/tmp/dummy'))
->getProcess();
$touchProcess->run();
return $touchProcess->isSuccessful(); // (b)
else
// ...
要测试所有情况,我需要能够模拟Process
对象以对应命令test
和touch
(这里:$testProcess
和$touchProcess
)。理想情况下,测试代码如下所示:
<?php
public function testToggleFileFileDoesNotExist()
$testProcess = \Mockery::mock('\Symfony\Component\Process\Process');
$testProcess->shouldReceive('isSuccessful')->andReturn(false); // (a)
$testProcess->shouldReceive('run');
$touchProcess = \Mockery::mock('\Symfony\Component\Process\Process');
$touchProcess->shouldReceive('isSuccessful')->andReturn(false); // (b)
$touchProcess->shouldReceive('run');
$builder = \Mockery::mock('\Symfony\Component\Process\ProcessBuilder');
$builder->shouldReceive('setPrefix("test")->getProcess')->andReturn($testProcess); // (c) Doesn't work!
$builder->shouldReceive('setPrefix("touch")->getProcess')->andReturn($touchProcess); // (c) Doesn't work!
$toggler = new Toggler();
$this->assertTrue($toggler->toggleFile($builder)); // see (b)
但是,由于 Mockery 不允许在调用链中使用参数,我对如何测试这种场景有点迷茫。有什么想法吗?
【问题讨论】:
【参考方案1】:这有点糟糕,但您可以尝试分别进入调用链的每个步骤并让它返回模拟 $builder。最后返回哪个进程取决于调用的顺序。
$builder->shouldRecieve('setPrefix')->with('test')->andReturn($builder);
$builder->shouldRecieve('setPrefix')->with('touch')->andReturn($builder);
$builder->shouldRecieve('getProcess')
->andReturnValues(array($testProcess, $touchProcess));
这感觉很乱,但这是迄今为止我能找到的唯一方法。 (如果您在发布此内容后提出了更好的建议,我很想知道。)
【讨论】:
以上是关于嘲弄:测试具有不同返回值的链式方法调用(此处:Symfony ProcessBuilder)的主要内容,如果未能解决你的问题,请参考以下文章
错误:在 null 上调用成员函数 create(),单元测试(嘲弄)