This came up trying to write a test for a method of a class that calls a mock method with a closure. How would you verify the closure being called?
I know that you would be able to assert that the parameter is an instance of Closure
. But how would you check anything about the closure?
For example how would you verify the function that is passed:
class SUT {
public function foo($bar) {
$someFunction = function() { echo "I am an anonymous function"; };
$bar->baz($someFunction);
}
}
class SUTTest extends PHPUnit_Framework_TestCase {
public function testFoo() {
$mockBar = $this->getMockBuilder('Bar')
->setMethods(array('baz'))
->getMock();
$mockBar->expects($this->once())
->method('baz')
->with( /** WHAT WOULD I ASSERT HERE? **/);
$sut = new SUT();
$sut->foo($mockBar);
}
}
You can't compare two closures in PHP. Is there a way in PHPUnit to execute the parameter passed in or in some way verify it?
If the closure has some side effects inside
SUT
that could be verified by the test after the mock invocation, usereturnCallback
to provide another closure to be called with the passed arguments and have its return value returned toSUT
. This will allow you to callSUT
's closure to cause the side effects.If you want to mock an anonymous function (callback) you can mock a class with
__invoke
method. For example:If you are using latest PHPUnit, you would have to use mock builder to do the trick:
You can also set expectations for method arguments or set a returning value, just the same way you would do it for any other method:
Your problem is that you aren't injecting your dependency (the closure), which always makes unit testing harder, and can make isolation impossible.
Inject the closure into
SUT::foo()
instead of creating it inside there and you'll find testing much easier.Here is how I would design the method (bearing in mind that I know nothing about your real code, so this may or may not be practical for you):