expects(new MethodInvokedAtIndex(0))->method('getMethod')->willReturn(1); * $mock->expects(new MethodInvokedAtIndex(1))->method('getMethod')->willReturn(2); * * $mock->getMethod(); // returns 1 * $mock->getMethod(); // returns 2 * * @package Magento\TestFramework\Matcher */ class MethodInvokedAtIndex implements \PHPUnit\Framework\MockObject\Matcher\Invocation { /** * @var int */ private $sequenceIndex; /** * @var int */ private $currentIndex = -1; /** * @var array */ private $indexes = []; /** * @param int $sequenceIndex */ public function __construct($sequenceIndex) { $this->sequenceIndex = $sequenceIndex; } /** * @return string */ public function toString(): string { return 'invoked at sequence index ' . $this->sequenceIndex; } /** * @param \PHPUnit\Framework\MockObject\Invocation $invocation * @return boolean */ public function matches(BaseInvocation $invocation): bool { /** @noinspection PhpUndefinedFieldInspection */ if (!isset($this->indexes[$invocation->getMethodName()])) { /** @noinspection PhpUndefinedFieldInspection */ $this->indexes[$invocation->getMethodName()] = 0; } else { /** @noinspection PhpUndefinedFieldInspection */ $this->indexes[$invocation->getMethodName()]++; } $this->currentIndex++; /** @noinspection PhpUndefinedFieldInspection */ return $this->indexes[$invocation->getMethodName()] == $this->sequenceIndex; } /** * @param BaseInvocation $invocation * @return mixed * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function invoked(BaseInvocation $invocation) { } /** * Verifies that the current expectation is valid. If everything is OK the * code should just return, if not it must throw an exception. * * @throws ExpectationFailedException */ public function verify(): void { if ($this->currentIndex < $this->sequenceIndex) { throw new ExpectationFailedException( \sprintf( 'The expected invocation at index %s was never reached.', $this->sequenceIndex ) ); } } }