在PHPUnit中,如何在对模拟方法的连续调用中指示不同的with()?

jam*_*mes 44 php phpunit mocking

我想用不同的预期参数两次调用我的模拟方法.这不起作用,因为expects($this->once())第二次调用会失败.

$mock->expects($this->once())
     ->method('foo')
     ->with('someValue');

$mock->expects($this->once())
     ->method('foo')
     ->with('anotherValue');

$mock->foo('someValue');
$mock->foo('anotherValue');
Run Code Online (Sandbox Code Playgroud)

我也尝试过:

$mock->expects($this->exactly(2))
     ->method('foo')
     ->with('someValue');
Run Code Online (Sandbox Code Playgroud)

但是如何添加with()来匹配第二个调用?

Dav*_*ess 63

你需要使用at():

$mock->expects($this->at(0))
     ->method('foo')
     ->with('someValue');

$mock->expects($this->at(1))
     ->method('foo')
     ->with('anotherValue');

$mock->foo('someValue');
$mock->foo('anotherValue');
Run Code Online (Sandbox Code Playgroud)

请注意,传递的索引将at()应用于对同一模拟对象的所有方法调用.如果是第二个方法调用,bar()则不会将参数更改为at().


Gun*_*h D 21

参考类似问题的答案,

从PHPUnit 4.1开始,您可以使用withConsecutive例如.

$mock->expects($this->exactly(2))
     ->method('set')
     ->withConsecutive(
         [$this->equalTo('foo'), $this->greaterThan(0)],
         [$this->equalTo('bar'), $this->greaterThan(0)]
       );
Run Code Online (Sandbox Code Playgroud)

如果你想让它在连续的通话中返回:

  $mock->method('set')
         ->withConsecutive([$argA1, $argA2], [$argB1], [$argC1, $argC2])
         ->willReturnOnConsecutiveCalls($retValueA, $retValueB, $retValueC);
Run Code Online (Sandbox Code Playgroud)

at()如果你可以避免使用它是不理想的,因为正如他们的文档声称的那样

at()匹配器的$ index参数指的是在给定模拟对象的所有方法调用中从零开始的索引.使用此匹配器时要小心,因为它可能导致脆弱的测试,这些测试与特定的实现细节过于紧密相关.