在使用PHPUnit模拟类时,如何防止调用原始方法?

时间:2016-03-07 00:27:15

标签: php unit-testing phpunit

根据我对PHPUnit文档的阅读,我希望以下代码创建一个AuthorizationChecker类的模拟,它将在调用isGranted()方法时返回false。但是,调用原始方法。我做错了什么?

    $auth = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AuthorizationChecker')
        ->disableOriginalConstructor()
        ->setMethods(['isGranted'])
        ->getMock();
    $auth->expects($this->any())
        ->method('isGranted')
        ->with($this->anything())
        ->will($this->returnValue(false));

    $this->assertFalse($auth->isGranted('TEST'));

将参数替换为setMethods(),使用null或空数组,或完全删除调用,无效。也不会删除expects()with()来电。

2 个答案:

答案 0 :(得分:1)

您要模拟的方法被声明为final,因此您无法按照in the doc描述的方式进行双倍测试:

  

限制:最终,私有和静态方法   请注意,最后,   私有和静态方法不能被存根或模拟。他们是   被PHPUnit的测试双重功能忽略并保留它们   原始行为。

您可以查看this获取部分解决方案。

希望这个帮助

答案 1 :(得分:1)

我能够通过模拟AuthorizationChecker类使用的所有内部函数然后将我的模拟注入容器来实现这一点。

    $tokenMock = $this->getMockBuilder( UsernamePasswordToken::class )
                      ->disableOriginalConstructor()
                      ->setMethods( array( 'isAuthenticated' ) )
                      ->getMock();
    $tokenMock->method( 'isAuthenticated' )
              ->willReturn( true );
    $tokenStorageMock = $this->getMockBuilder( TokenStorage::class )
                             ->disableOriginalConstructor()
                             ->setMethods( array( 'getToken' ) )
                             ->getMock();
    $tokenStorageMock->method( 'getToken' )
                     ->willReturn( $tokenMock );
    $authenticationManagerMock = $this->getMockBuilder( AuthenticationManagerInterface::class )
                                      ->disableOriginalConstructor()
                                      ->getMock();
    $accessDecisionManagerMock = $this->getMockBuilder( AccessDecisionManager::class )
                                      ->disableOriginalConstructor()
                                      ->setMethods( array( 'decide' ) )
                                      ->getMock();
    $accessDecisionManagerMock->method( 'decide' )
                              ->willReturn( 'true' );
    $authorizationCheckerMock = $this->getMockBuilder( AuthorizationChecker::class )
                                     ->setConstructorArgs(
                                         array(
                                             $tokenStorageMock,
                                             $authenticationManagerMock,
                                             $accessDecisionManagerMock,
                                             false
                                         )
                                     )
                                     ->setMethods( array( 'isGranted' ) )
                                     ->getMock();
    $authorizationCheckerMock->method( 'isGranted' )
                             ->will( $this->returnValue( true ) );
    $this->getContainer()
         ->set( 'security.authorization_checker', $authorizationCheckerMock );