PHPUnit: how to mock multiple method calls with multiple arguments and no straight order?
phpunit, unit-testing, zend-framework2
Solution
You can try with `willReturnCallback` or `willReturnMap` strategy, as example of `willReturnCallback`:
public function testReturnValue()
{
$firstServiceMock = $this->createMock(FirstServiceInterface::class);
$secondServiceMock = $this->createMock(SecondServiceInterface::class);
$serviceManagerMock = $this->createMock(ServiceLocatorInterface::class);
$serviceManagerMock->expects($this->any())
->method('get')
->willReturnCallback(
function ($key) use($firstServiceMock, $secondServiceMock) {
if ($key == 'FirstServiceKey') {
return $firstServiceMock;
}
if ($key == 'SecondServiceKey') {
return $secondServiceMock;
}
throw new \InvalidArgumentException; // or simply return;
}
);
$serviceFactory = new ServiceFactory($serviceManagerMock);
$result = $serviceFactory->createService();
}
Hope this help
Problem
I need to test following function: ``` [...] public function createService(ServiceLocatorInterface $serviceManager) { $firstService = $serviceManager->get('FirstServiceKey'); $secondService = $serviceManager->get('SecondServiceKey'); return new SnazzyService($firstService, $secondService); } [...] ``` I know, I might test it this way: ``` class MyTest extends \PHPUnit_Framework_TestCase { public function testReturnValue() { $firstServiceMock = $this->createMock(FirstServiceInterface::class); $secondServiceMock = $this->createMock(SecondServiceInterface::class); $serviceManagerMock = $this->createMock(ServiceLocatorInterface::class); $serviceManagerMock->expects($this->at(0)) ->method('get') ->with('FirstServiceKey') ->will($this->returnValue($firstService)); $serviceManagerMock->expects($this->at(1)) ->method('get') ->with('SecondServiceKey') ->will($this->returnValue($secondServiceMock)); $serviceFactory = new ServiceFactory($serviceManagerMock); $result = $serviceFactory->createService(); } [...] ``` or ``` [...] public function testReturnValue() { $firstServiceMock = $this->createMock(FirstServiceInterface::class); $secondServiceMock = $this->createMock(SecondServiceInterface::class); $serviceManagerMock = $this->createMock(ServiceLocatorInterface::class); $serviceManagerMock->expects($this->any()) ->method('get') ->withConsecutive( ['FirstServiceKey'], ['SecondServiceKey'], ) ->willReturnOnConsecutiveCalls( $this->returnValue($firstService), $this->returnValue($secondServiceMock) ); $serviceFactory = new ServiceFactory($serviceManagerMock); $result = $serviceFactory->createService(); } [...] ``` Both workes fine, but if I swap the ->get(xxx) lines in the createService function, both tests will fail. So, how do I have to change the testcases which doesn't need a specific sequenz for the parameters 'FirstServiceKey', 'SecondServiceKey, ...