Phpunit 如何模拟方法在第一次调用时返回值X,在rest调用时返回值Y?

Phpunit 如何模拟方法在第一次调用时返回值X,在rest调用时返回值Y?,phpunit,Phpunit,如何模拟方法在第一次调用时返回值X,在rest调用时返回值Y 下面的解决方案很有效,但我不想多次编写$Y: $o->expects($this->any()) ->method('foo') ->will($this->onConsecutiveCalls($X, $Y, $Y, $Y, $Y, $Y)); 以下解决方案每次都将返回$Y: $o->expects($this->any()) ->method('fo

如何模拟方法在第一次调用时返回值X,在rest调用时返回值Y

下面的解决方案很有效,但我不想多次编写
$Y

$o->expects($this->any())
      ->method('foo')
      ->will($this->onConsecutiveCalls($X, $Y, $Y, $Y, $Y, $Y));
以下解决方案每次都将返回
$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
。然而,这不仅仅是为每个返回值键入$Y,而是更多的代码行,因此,如果在第一次调用后对doSomething的每次调用都需要多次返回相同的值,我只会使用以下版本:

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());
}

您可以在PHPUnit的
returnCallback
函数中使用匿名函数,而不是
onConsecutiveCalls
。然而,这不仅仅是为每个返回值键入$Y,而是更多的代码行,因此,如果在第一次调用后对doSomething的每次调用都需要多次返回相同的值,我只会使用以下版本:

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());
}