如何在第一次调用时将方法模拟为 return 值 X,在其余调用中模拟为 Y?

How to mock method to return value X at first call, and Y on rest calls?

如何模拟方法 return 在第一次调用时赋值 X,在其余调用时赋值 Y?

下面的解决方案可行,但我不想写 $Y 这么多次:

$o->expects($this->any())
      ->method('foo')
      ->will($this->onConsecutiveCalls($X, $Y, $Y, $Y, $Y, $Y));

以下解决方案每次都会 return $Y:

$o->expects($this->any())
    ->method('foo')
    ->will($this->returnValue($Y));
$o->expects($this->at(0))
    ->method('foo')
    ->will($this->returnValue($X));

您可以通过在 PHPUnit 的 returnCallback 函数中使用匿名函数而不是 onConsecutiveCalls 来完成此操作。但是,这比为每个 return 值简单地输入 $Y 多了很多行代码,所以如果 every 在第一个之后调用 doSomething,我只会使用下面的版本调用需要多次 return 相同的值:

class Example
{
    function doSomething() { }
}

// within your test class
public function testConsecutiveCallbacks()
{
    $counter = 0;
    $stub = $this->createMock(Example::class);
    $stub
        ->method('doSomething')
        ->will($this->returnCallback(function () use (&$counter) {
            $counter++;
            if ($counter == 1) {
                return 'value for x';
            }
            return 'value for y';
        }));
    $this->assertEquals('value for x', $stub->doSomething());
    $this->assertEquals('value for y', $stub->doSomething());
    $this->assertEquals('value for y', $stub->doSomething());
    $this->assertEquals('value for y', $stub->doSomething());
}