Closure return values in function-mocker

Function-mocker uses closures to set return values: need I say more?

No mappings

A method PHPUnit supplies and function-mocker does not supply is the possibility to set a return value map when replacing method (or a function or a static method in function-mocker case).
Luckily the sentence above is not true; function-mocker allows the return value to be set either to a value like this

FunctionMocker::replace('someFunction', 23);

$this->assertEquals(23, someFunction());

or to a callback function like this

FunctionMocker::replace('someFunction', function($arg){
    return $arg * 2;

$this->assertEquals(46, someFunction(23));

and this second possibility is the one that can be leveraged to create an argument to return value map. The FunctionMocker::replace method will pass the arguments the function is called with to the closure, that’s what’s being used in the example above.

Using closure return values

If I want to stub out a function, a static method or an instance method to return a value in a map the possibility offered by a closure function makes the thing trivial

$map = [
    1 => ['plain' => 'Lorem', 'bold' => '<b>Lorem</b>'],
    2 => ['plain' => 'Ipsum', 'bold' => '<b>Ipsum</b>'],

FunctionMocker::replace('Post::getContent', function($id, $format) use ($map){
    return $map[$id][$format];

$this->assertEquals('Lorem', Post::getContent(1, 'plain'));
$this->assertEquals('<b>Lorem</b>', Post::getContent(1, 'bold'));
$this->assertEquals('Ipsum', Post::getContent(2, 'plain'));

But since it’s a closure I’m dealing with I can pack way more logic in it and use the full power of the anonymous function to, as an example, simulate a lagging response

FunctionMocker::replace('Feed::getLatest', function() use($feedStub){
    return $feedStub;

or change the behaviour of the return value over time

FunctionMocker::replace('TwitterApi::queryFor', function($tag) use (&$calls, $messageTemplate){
        if($calls > 5) {

            return ['status' => 0, 'message' => 'API query limit reached'];
        $calls += 1;
        $message = str_replace('%%tag%%', $tag, $messageTemplate);

        return ['status' => 1, 'message' => $message];

So, using a lambda function, sky is the limit.