【问题标题】:PHPunit mock - call a function in a returned mockPHPunit mock - 在返回的 mock 中调用函数
【发布时间】:2013-11-17 08:49:14
【问题描述】:

我对 phpunit 和 mocking 很陌生,我想在我的 symfony2 项目中测试一个 Listener,什么是内核异常监听器。

这是我要测试的类:

public function onKernelException(GetResponseForExceptionEvent $event)
{
    $code = $event->getException()->getCode();
    if($code == 403)
    {
        $request = $event->getRequest();
        $session = $request->getSession();
        $session->getFlashBag()->add('notice', 'message');
        $session->set('hardRedirect', $request->getUri());
    }
}

首先我只是想测试一下,所以如果代码是 404 什么都不会发生,这是我写的测试:

public function testWrongStatusCode()
{
    $exceptionMock = $this->getMock('Exception')
                      ->expects($this->once())
                      ->method('getCode')
                      ->will($this->returnValue('404'));

    $eventMock = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent')
                      ->disableOriginalConstructor()
                      ->getMock();
    $eventMock->expects($this->once())
              ->method('getException')
              ->will($this->returnValue($exceptionMock));

//here call the listener
}

但是 PHPunit 说,getCode 函数从未被调用过。

【问题讨论】:

    标签: unit-testing symfony mocking phpunit


    【解决方案1】:

    您不能像尝试过的那样使用“链接”。原因是getMockwill 方法返回不同的对象。这就是为什么你会丢失你真正的模拟对象。试试这个:

    $exceptionMock = $this->getMock('\Exception');
    $exceptionMock->expects($this->once())
        ->method('getCode')
        ->will($this->returnValue('404'));
    

    编辑

    好的。问题是你不能模拟 getCode 方法,因为它是 final 并且不可能用 PHPUnit 模拟 finalprivate 方法。

    我的建议是:只需准备一个你想要的异常对象,并将其作为返回值传递给事件模拟:

    $exception = new \Exception("", 404);
    (...)
    $eventMock->expects($this->once())
        ->method('getException')
        ->will($this->returnValue($exception));
    

    【讨论】:

    • 其实我试过这个,在我发布之前也没有工作,同样的错误,方法应该被调用1次,实际上被调用0次。我还对 $event->getException() 的类进行了 var_exported,它是 Mock_Exception 类。
    • 谢谢,这就是解决方案。以后我会尽量不要忘记这一点。
    【解决方案2】:

    这就是我模拟 getCode() 函数的方式。它实际上是从 ResponseInterface::getStatusCode() 函数调用的,所以这就是你需要模拟的:

    $guzzle->shouldReceive('get')
        ->once()
        ->with(
            $url
        )
        ->andThrows(new ClientException(
            "",
            Mockery::mock(RequestInterface::class),
            Mockery::mock(ResponseInterface::class, [
                'getStatusCode' => 404,
            ]),
        ));
    

    【讨论】:

      【解决方案3】:

      您可以将mockery library 与 PHPUnit 一起使用,这是一个很棒的工具,让生活更轻松。

      $exceptionMock = \Mockery::mock('GetResponseForExceptionEvent');
      $exceptionMock->shouldReceive('getException->getCode')->andReturn('404');
      

      查看文档了解更多...希望您会喜欢它。

      【讨论】:

      • 它通常是一部分,在 Symfony 中 $this->getMock 使用嘲弄 如果你阅读了前面的答案,你不能模拟一般的异常,这里的问题是什么,或者至少是 getCode功能。
      猜你喜欢
      • 2015-04-04
      • 2020-03-01
      • 1970-01-01
      • 2011-11-23
      • 2012-08-07
      • 1970-01-01
      • 2017-04-02
      • 1970-01-01
      • 2020-01-25
      相关资源
      最近更新 更多