PHPUnit:如何使用多个参数模拟多个方法调用?

Tho*_*mas 51 php tdd phpunit mocking

我正在为使用PHPUnit的方法编写单元测试.我正在测试的方法在同一个对象上调用同一个方法3次,但使用不同的参数集.我的问题类似于这里这里提出的问题

其他帖子中提出的问题与只采用一个论点的模拟方法有关.

但是,我的方法需要多个参数,我需要这样的东西:

$mock->expects($this->exactly(3))
     ->method('MyMockedMethod')
     ->with($this->logicalOr($this->equalTo($arg1, $arg2, arg3....argNb),
                             $this->equalTo($arg1b, $arg2b, arg3b....argNb),
                             $this->equalTo($arg1c, $arg2c, arg3c....argNc)
         ))
Run Code Online (Sandbox Code Playgroud)

此代码不起作用,因为equalTo()只验证一个参数.给它多个参数会引发异常:

PHPUnit_Framework_Constraint_IsEqual :: __ construct()的参数#2必须是数字

有没有办法对logicalOr具有多个参数的方法进行模拟?

提前致谢.

dr *_*ter 77

在我的情况下,答案结果很简单:

$this->expects($this->at(0))
    ->method('write')
    ->with(/* first set of params */);

$this->expects($this->at(1))
    ->method('write')
    ->with(/* second set of params */);
Run Code Online (Sandbox Code Playgroud)

关键是使用$this->at(n),n作为方法的第N次调用.我logicalOr()试过的任何变种都无法做任何事情.

  • matcher 的快速注释已被弃用,并将在 phpunit 10 中删除,应使用 cody 的答案,包括 withConsecutive (5认同)
  • 这里只需注意:`$ this-> at()`的索引从零开始,但在模拟对象上通过_every_方法调用增加.@GeoffreyBrier,这可能就是为什么它,对你来说是索引1 ....阅读这里获取更多信息:http://phpunit.de/manual/current/en/test-doubles.html#测试doubles.mock-objects.tables.matchers (3认同)
  • @drHannibalLecter这是有效的,但这里的问题是它很难编码你的测试来关心测试用例的内部实现. (2认同)

Cod*_*Ray 35

对于那些希望匹配输入参数并为多个调用提供返回值的人来说......这对我有用:

    $mock->method('myMockedMethod')
         ->withConsecutive([$argA1, $argA2], [$argB1, $argB2], [$argC1, $argC2])
         ->willReturnOnConsecutiveCalls($retValue1, $retValue2, $retValue3);
Run Code Online (Sandbox Code Playgroud)


scr*_*tin 25

对方法调用进行存根以从地图返回值

$map = array(
    array('arg1_1', 'arg2_1', 'arg3_1', 'return_1'),
    array('arg1_2', 'arg2_2', 'arg3_2', 'return_2'),
    array('arg1_3', 'arg2_3', 'arg3_3', 'return_3'),
);
$mock->expects($this->exactly(3))
    ->method('MyMockedMethod')
    ->will($this->returnValueMap($map));
Run Code Online (Sandbox Code Playgroud)

或者你可以使用

$mock->expects($this->exactly(3))
    ->method('MyMockedMethod')
    ->will($this->onConsecutiveCalls('return_1', 'return_2', 'return_3'));
Run Code Online (Sandbox Code Playgroud)

如果您不需要指定输入参数


小智 12

如果有人在没有查看phpunit文档中的相应部分的情况下找到它,您可以使用withConsecutive方法

$mock->expects($this->exactly(3))
     ->method('MyMockedMethod')
     ->withConsecutive(
         [$arg1, $arg2, $arg3....$argNb],
         [arg1b, $arg2b, $arg3b....$argNb],
         [$arg1c, $arg2c, $arg3c....$argNc]
         ...
     );
Run Code Online (Sandbox Code Playgroud)

唯一的缺点是代码必须按照提供的参数顺序调用MyMockedMethod.我还没有找到办法解决这个问题.

  • 我相信这就是“地图”函数的用途,例如 willReturnMap 或 returnValueMap - 就像从参数到返回的查找。 (2认同)