Search code examples
phpcakephpphpunit

PHPUnit's returnValueMap not yielding expected results


I'm trying to use PHPUnit's returnValueMap() to stub out the results of a read. It isn't yielding the expected results, but an equivalent returnCallback() does. I've made my test case available if you'd like to inspect it yourself.

returnValueMap()

$enterprise = $this->getMock('Enterprise', array('field'));
$enterprise->expects($this->any())
    ->method('field')
    ->will($this->returnValueMap(array(
        array('subscription_id', null),
        array('name', 'Monday Farms')
    )));
$enterprise->subscribe('basic');

Results:

Subscription ID: NULL
Name: NULL

returnCallback()

$enterprise = $this->getMock('Enterprise', array('field'));
$enterprise->expects($this->any())
    ->method('field')
    ->will($this->returnCallback(function ($arg) {
        $map = array(
            'subscription_id' => null,
            'name' => 'Monday Farms'
        );
        return $map[$arg];
    }));
$enterprise->subscribe('basic');

Results:

Subscription ID: NULL
Name: string(12) "Monday Farms"

Enterprise::subscribe

public function subscribe() {
    echo 'Subscription ID: ';
    var_dump($this->field('subscription_id'));
    echo 'Name: ';
    var_dump($this->field('name'));
}

Why doesn't returnValueMap() work as I expect it to? What exactly am I missing?


Solution

  • I had the same problem and eventually found out that returnValueMap() has to map all parameters of your function, including optional ones, then the desired return value.

    Example function from Zend Framework:

    public function getParam($key, $default = null)
    {
        $key = (string) $key;
        if (isset($this->_params[$key])) {
            return $this->_params[$key];
        }
    
        return $default;
    }
    

    Has to mapped like this:

    $request->expects($this->any())
            ->method('getParam')
            ->will($this->returnValueMap(array(array($param, null, $value))));
    

    Without the null in the middle, it won't work.