Closure mock #257

Open
mnapoli opened this Issue Oct 2, 2015 · 3 comments

Projects

None yet

4 participants

@mnapoli
mnapoli commented Oct 2, 2015

It would be great to be able to create a mock that:

  • behaves like a closure
  • allows to spy if/how it is called

Example:

$mock = $this->getMockCallback();
$mock->expect($this->once())
    ->with(1, 2)
    ->willReturn(3);

The mock would mock that behavior while allowing to spy calls:

$callback = function ($a, $b) {
    return $a + $b;
}
@sebastianbergmann
Owner

I might accept a pull request that implements this but I won't implement it myself.

@ThomasWeinert
Collaborator

It is nearly possible with the current API.

class ClosureMockTest extends PHPUnit_Framework_TestCase {

  public function testClosureMock() {
    $mock = $this->getMockCallback();
    $mock
      ->expects($this->once())
      ->method('__invoke') // method matcher
      ->with(1, 2)
      ->willReturn(3);

    $mock(3, 4);
  }

  private function getMockCallback() {
    $mock = $this
      ->getMockBuilder('object')
      ->setMethods(['__invoke'])
      ->getMock();
    return $mock;
  }
}

You still need the method matcher (it is required). I see two possible solutions:

  1. Return a mock with a modified expects() that adds the method matcher.
  2. Use a pseudo class name like callable and some special handling.
@enumag
enumag commented Aug 30, 2016 edited

Just found out that this actually is possible with the current API:

$mock = $this->createPartialMock(\stdClass::class, ['__invoke']);
$mock
      ->expects(self::once())
      ->method('__invoke')
      ->with(1, 2)
      ->willReturn(3);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment