大家好我需要测试一段调用另一个类的函数的代码我现在无法编辑。
我只需要测试它但问题是这个函数有一个通过引用传递的值和一个返回的值,所以我不知道如何模拟它。
这是列类的功能:
public function functionWithValuePassedByReference(&$matches = null)
{
$regex = 'my regex';
return ($matches === null) ? preg_match($regex, $this->field) : preg_match($regex, $this->field, $matches);
}
这是调用的地方,我需要模拟的地方:
$matches = [];
if ($column->functionWithValuePassedByReference($matches)) {
if (strtolower($matches['parameters']) == 'distinct') {
//my code
}
}
所以我试过了
$this->columnMock = $this->createMock(Column::class);
$this->columnMock
->method('functionWithValuePassedByReference')
->willReturn(true);
如果我这样做,则返回错误索引parameters
显然不存在,所以我试过这个:
$this->columnMock = $this->createMock(Column::class);
$this->columnMock
->method('functionWithValuePassedByReference')
->with([])
->willReturn(true);
但同样的错误,我怎么能模仿那个功能?
由于
答案 0 :(得分:4)
您可以使用->willReturnCallback()
修改参数并返回值。所以你的模拟会变成这样:
$this->columnMock
->method('functionWithValuePassedByReference')
->with([])
->willReturnCallback(function(&$matches) {
$matches = 'foo';
return True;
});
为了使其正常工作,您需要在构建模拟时关闭克隆模拟的参数。所以你的模拟对象就像这样构建
$this->columnMock = $this->getMockBuilder('Column')
->setMethods(['functionWithValuePassedByReference'])
->disableArgumentCloning()
->getMock();
这真的是代码味道,顺便说一句。我意识到你声明你无法改变你正在嘲笑的代码。但是对于其他看这个问题的人来说,这样做会导致代码产生副作用,并且可能成为修复bug的非常令人沮丧的原因。