PHPUnit测试方法多次调用,具有特定参数,没有特定的顺序

时间:2016-12-29 23:08:02

标签: php unit-testing phpunit

我有一个关于测试某些方法使用特定参数调用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三次,每次都以任何顺序传递不同的指定参数吗?

上面的类和示例都是简化的。它描述了我的情况但不是我的确切情况。所有重要细节都在这个问题中。

提前致谢

2 个答案:

答案 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将包含方法执行方式的完整记录。您可以遍历它并检查您的需求。