首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用闭包进行PHPUnit测试

使用闭包进行PHPUnit测试
EN

Stack Overflow用户
提问于 2013-10-09 02:10:55
回答 3查看 13.7K关注 0票数 21

这是在尝试为调用带有闭包的模拟方法的类的方法编写测试时出现的。您将如何验证被调用的闭包?

我知道您可以断言该参数是Closure的一个实例。但是你怎么检查闭包呢?

例如,如何验证传递的函数:

代码语言:javascript
复制
 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中有没有一种方法来执行传入的参数,或者以某种方式验证它?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-09 02:39:10

你的问题是你没有注入你的依赖(闭包),这总是使单元测试变得更加困难,并且可能使隔离变得不可能。

把闭包注入到SUT::foo()中,而不是在里面创建它,你会发现测试变得更容易了。

下面是我将如何设计该方法(请记住,我对您的真实代码一无所知,因此这对您来说可能实用,也可能不实用):

代码语言:javascript
复制
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);
    }
}
票数 9
EN

Stack Overflow用户

发布于 2015-11-20 22:18:00

如果你想模拟一个匿名函数(回调),你可以用__invoke方法模拟一个类。例如:

代码语言:javascript
复制
$shouldBeCalled = $this->getMock(\stdClass::class, ['__invoke']);
$shouldBeCalled->expects($this->once())
    ->method('__invoke');

$someServiceYouAreTesting->testedMethod($shouldBeCalled);

如果您使用的是最新的PHPUnit,则必须使用模拟构建器来完成此操作:

代码语言:javascript
复制
$shouldBeCalled = $this->getMockBuilder(\stdClass::class)
    ->setMethods(['__invoke'])
    ->getMock();

$shouldBeCalled->expects($this->once())
    ->method('__invoke');

$someServiceYouAreTesting->testedMethod($shouldBeCalled);

您还可以为方法参数设置期望或设置返回值,这与对任何其他方法执行此操作的方式相同:

代码语言:javascript
复制
$shouldBeCalled->expects($this->once())
    ->method('__invoke')
    ->with($this->equalTo(5))
    ->willReturn(15);
票数 18
EN

Stack Overflow用户

发布于 2013-10-10 01:10:19

如果闭包在SUT中有一些副作用,可以通过模拟调用后的测试进行验证,那么可以使用returnCallback提供另一个要用传递的参数调用的闭包,并将其返回值返回给SUT。这将允许您调用SUT的闭包来引起副作用。

代码语言:javascript
复制
 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));
     }
 }
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19255171

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档