diff --git a/src/Stub/ReturnValueMap.php b/src/Stub/ReturnValueMap.php index 8b31a587..c16b3c91 100644 --- a/src/Stub/ReturnValueMap.php +++ b/src/Stub/ReturnValueMap.php @@ -29,9 +29,9 @@ public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation) continue; } - $return = array_pop($map); - if ($invocation->parameters === $map) { - return $return; + $returnValue = $this->getReturnValue(array_pop($map)); + if ($this->compare($invocation->parameters, $map)) { + return $returnValue->invoke($invocation); } } @@ -42,4 +42,32 @@ public function toString() { return 'return value from a map'; } + + /** + * @param array $actual + * @param array $expected + * @return bool + */ + protected function compare($actual, $expected) { + foreach ($expected as $index => $value) { + if ($value instanceof PHPUnit_Framework_Constraint) { + if ($value->evaluate($actual[$index], '', true) === false) { + return false; + } + } else { + if ($value !== $actual[$index]) { + return false; + } + } + } + + return true; + } + + protected function getReturnValue($value) { + if (!$value instanceOf PHPUnit_Framework_MockObject_Stub) { + return new PHPUnit_Framework_MockObject_Stub_Return($value); + } + return $value; + } } diff --git a/tests/MockObject/Stub/ReturnValueMapTest.php b/tests/MockObject/Stub/ReturnValueMapTest.php new file mode 100644 index 00000000..e7c2e91a --- /dev/null +++ b/tests/MockObject/Stub/ReturnValueMapTest.php @@ -0,0 +1,92 @@ +getMockBuilder(AnInterface::class) + ->getMock(); + + $mock->expects($this->any()) + ->method('doSomething') + ->will($this->returnValueMap($map)); + + $this->assertEquals('d', $mock->doSomething('a', 'b', 'c')); + } + + /** + * @test + **/ + public function accepts_framework_matchers() { + $map = [ + [$this->lessThan(2), 1], + [$this->greaterThanOrEqual(2), 2] + ]; + + $mock = $this->getMockBuilder(AnInterface::class) + ->getMock(); + + $mock->expects($this->any()) + ->method('doSomething') + ->will($this->returnValueMap($map)); + + $this->assertEquals(1, $mock->doSomething(0)); + $this->assertEquals(2, $mock->doSomething(100)); + } + + /** + * @test + **/ + public function accepts_stub_for_return_value() { + $callback = new PHPUnit_Framework_MockObject_Stub_ReturnCallback( + function($arg) { return $arg + 1; } + ); + + $map = [ + [$this->lessThan(2), 1], + [$this->greaterThanOrEqual(2), $callback] + ]; + + $mock = $this->getMockBuilder(AnInterface::class) + ->getMock(); + + $mock->expects($this->any()) + ->method('doSomething') + ->will($this->returnValueMap($map)); + + + $this->assertEquals(3, $mock->doSomething(2)); + } + + /** + * @test + **/ + public function returns_null_if_no_match_found() + { + $map = [ + ['a', 'b', 'c', 'd'], + ]; + + $mock = $this->getMockBuilder(AnInterface::class) + ->getMock(); + + $mock->expects($this->any()) + ->method('doSomething') + ->will($this->returnValueMap($map)); + + $this->assertEquals(null, $mock->doSomething('foo', 'bar')); + } +} diff --git a/tests/MockObjectTest.php b/tests/MockObjectTest.php index d7e74fb7..b676932a 100644 --- a/tests/MockObjectTest.php +++ b/tests/MockObjectTest.php @@ -212,36 +212,6 @@ public function testStubbedReturnValue() $this->assertEquals('something', $mock->doSomething()); } - public function testStubbedReturnValueMap() - { - $map = [ - ['a', 'b', 'c', 'd'], - ['e', 'f', 'g', 'h'] - ]; - - $mock = $this->getMockBuilder(AnInterface::class) - ->getMock(); - - $mock->expects($this->any()) - ->method('doSomething') - ->will($this->returnValueMap($map)); - - $this->assertEquals('d', $mock->doSomething('a', 'b', 'c')); - $this->assertEquals('h', $mock->doSomething('e', 'f', 'g')); - $this->assertEquals(null, $mock->doSomething('foo', 'bar')); - - $mock = $this->getMockBuilder(AnInterface::class) - ->getMock(); - - $mock->expects($this->any()) - ->method('doSomething') - ->willReturnMap($map); - - $this->assertEquals('d', $mock->doSomething('a', 'b', 'c')); - $this->assertEquals('h', $mock->doSomething('e', 'f', 'g')); - $this->assertEquals(null, $mock->doSomething('foo', 'bar')); - } - public function testStubbedReturnArgument() { $mock = $this->getMockBuilder(AnInterface::class)