这是在尝试为调用带有闭包的模拟方法的类的方法编写测试时出现的。您将如何验证被调用的闭包?
我知道您可以断言该参数是Closure
的一个实例。但是你怎么检查闭包呢?
例如,如何验证传递的函数:
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);
}
}
在PHP中不能比较两个闭包。在PHPUnit中有没有一种方法来执行传入的参数,或者以某种方式验证它?
发布于 2013-10-09 02:39:10
你的问题是你没有注入你的依赖(闭包),这总是使单元测试变得更加困难,并且可能使隔离变得不可能。
把闭包注入到SUT::foo()
中,而不是在里面创建它,你会发现测试变得更容易了。
下面是我将如何设计该方法(请记住,我对您的真实代码一无所知,因此这对您来说可能实用,也可能不实用):
class SUT
{
public function foo($bar, $someFunction)
{
$bar->baz($someFunction);
}
}
class SUTTest extends PHPUnit_Framework_TestCase
{
public function testFoo()
{
$someFunction = function() {};
$mockBar = $this->getMockBuilder('Bar')
->setMethods(array('baz'))
->getMock();
$mockBar->expects($this->once())
->method('baz')
->with($someFunction);
$sut = new SUT();
$sut->foo($mockBar, $someFunction);
}
}
发布于 2015-11-20 22:18:00
如果你想模拟一个匿名函数(回调),你可以用__invoke
方法模拟一个类。例如:
$shouldBeCalled = $this->getMock(\stdClass::class, ['__invoke']);
$shouldBeCalled->expects($this->once())
->method('__invoke');
$someServiceYouAreTesting->testedMethod($shouldBeCalled);
如果您使用的是最新的PHPUnit,则必须使用模拟构建器来完成此操作:
$shouldBeCalled = $this->getMockBuilder(\stdClass::class)
->setMethods(['__invoke'])
->getMock();
$shouldBeCalled->expects($this->once())
->method('__invoke');
$someServiceYouAreTesting->testedMethod($shouldBeCalled);
您还可以为方法参数设置期望或设置返回值,这与对任何其他方法执行此操作的方式相同:
$shouldBeCalled->expects($this->once())
->method('__invoke')
->with($this->equalTo(5))
->willReturn(15);
发布于 2013-10-10 01:10:19
如果闭包在SUT
中有一些副作用,可以通过模拟调用后的测试进行验证,那么可以使用returnCallback
提供另一个要用传递的参数调用的闭包,并将其返回值返回给SUT
。这将允许您调用SUT
的闭包来引起副作用。
class SUT {
public function foo($bar) {
$someFunction = function() { return 5 * 3; };
return $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')
->will($this->returnCallback(function ($someFunction) {
return $someFunction();
}));
$sut = new SUT();
self::assertEquals(15, $sut->foo($mockBar));
}
}
https://stackoverflow.com/questions/19255171
复制相似问题