我有一个关于测试某些方法使用特定参数调用x次的问题。
情况:
我有一个Grid类。它处理一个二维数组。它包含一个方法
public function setCell($x, $y, $value) : void
在坐标$ x和$ y设置值$。
接下来我有一个GridShifter类。它包含一个方法
public function shiftRow($grid : Grid, $rowNumber : int) : void
此方法将行号$ rowNumber的所有值都移到右侧。例如:
$grid = new Grid([[1, 2, 3]]);
$gridShifter->shiftRow($grid, 1);
// prints two dimensional array
print_r($grid->printGrid());
将导致
[[3, 1, 2]]
问题:
我想测试GridShifter的shiftRow方法,而不是通过模拟this方法测试Grid类的setCell功能,并检查调用该方法的次数(对于此示例3)并检查调用的参数。 / p>
对我不起作用的解决方案:
我尝试了几种解决方案。 $ gridMock是Grid类的模拟。
1)withConsecutive或at($ x)
$gridMock->expect($this->exactly(3))->method('setCell')->withConsecutive(
[1, 1, 3],
[1, 2, 2],
[1, 3, 1]
);
这通过了我的测试,但这对我不起作用,因为它也测试了它执行的顺序。我对它们被调用的顺序不感兴趣。
2)returnValueMap
$gridMock->expect($this->exactly(3))->method('setCell')->will($this-returnValueMap([
[1, 1, 3],
[1, 2, 2],
[1, 3, 1]
]);
这并不能测试我的需求。在这种情况下,当使用参数1,1和3调用setCell三次而不使用其他参数调用setCell时,测试也将通过
3)withConsecutive with logicalOr
$gridMock->expect($this->exactly(3))->method('setCell')->withConsecutive(
$this->logicalOr(
[1, 1, 3],
[1, 2, 2],
[1, 3, 1]
)
);
这也通过了我的测试,但与解决方案2有同样的问题。它没有测试是否所有三组参数都被调用。
有人会想到一个解决方案,它将在shiftCell中调用setCell三次,每次都以任何顺序传递不同的指定参数吗?
上面的类和示例都是简化的。它描述了我的情况但不是我的确切情况。所有重要细节都在这个问题中。
提前致谢
答案 0 :(得分:0)
withCallback
是内置方法不起作用的方法。在数组中添加预期的参数,然后在回调中检查数组中是否存在参数(按特定顺序) - 如果是,则从数组中删除它们(因此相同参数的2次将无法通过测试);如果没有 - 测试失败
callback()约束可用于更复杂的参数 验证。此约束仅将PHP回调作为其回调 论点。 PHP回调将接收要验证的参数 它唯一的参数,如果参数通过则应该返回true 验证,否则为假。
从PHPUnit手册 - Test doubles
答案 1 :(得分:0)
您可以使用回调闭包。例如:
$executions = [];
$grid = $this->getMockBuilder('Grid')->getMock();
$grid->expects($this->any())->method('setCell')->will($this->returnCallback(
function($x, $y, $value) use ($executions) {
$executions[] = func_get_args();
}
));
执行后,变量$ executions将包含方法执行方式的完整记录。您可以遍历它并检查您的需求。