phpunit-testingmockingphpunit

How can I get PHPUnit MockObjects to return different values based on a parameter?


I've got a PHPUnit mock object that returns 'return value' no matter what its arguments:

// From inside a test...
$mock = $this->getMock('myObject', 'methodToMock');
$mock->expects($this->any))
     ->method('methodToMock')
     ->will($this->returnValue('return value'));

What I want to be able to do is return a different value based on the arguments passed to the mock method. I've tried something like:

$mock = $this->getMock('myObject', 'methodToMock');

// methodToMock('one')
$mock->expects($this->any))
     ->method('methodToMock')
     ->with($this->equalTo('one'))
     ->will($this->returnValue('method called with argument "one"'));

// methodToMock('two')
$mock->expects($this->any))
     ->method('methodToMock')
     ->with($this->equalTo('two'))
     ->will($this->returnValue('method called with argument "two"'));

But this causes PHPUnit to complain if the mock isn't called with the argument 'two', so I assume that the definition of methodToMock('two') overwrites the definition of the first.

So my question is: Is there any way to get a PHPUnit mock object to return a different value based on its arguments? And if so, how?


Solution

  • Use a callback. e.g. (straight from PHPUnit documentation):

    <?php
    class StubTest extends PHPUnit_Framework_TestCase
    {
        public function testReturnCallbackStub()
        {
            $stub = $this->getMock(
              'SomeClass', array('doSomething')
            );
     
            $stub->expects($this->any())
                 ->method('doSomething')
                 ->willReturnCallback('callback');
     
            // $stub->doSomething() returns callback(...)
        }
    }
     
    function callback() {
        $args = func_get_args();
        // ...
    }
    ?>
    

    Do whatever processing you want in the callback() and return the result based on your $args as appropriate.