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

如何防止在使用PHPUnit模拟类时调用原始方法?,php,unit-testing,phpunit,Php,Unit Testing,Phpunit,根据我对PHPUnit文档的阅读,我希望下面的代码创建一个AuthorizationChecker类的模拟,当调用isgrated()方法时,该类将返回false。但是,将调用原始方法。我做错了什么 $auth = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AuthorizationChecker') ->disableOriginalConstructor()

根据我对PHPUnit文档的阅读,我希望下面的代码创建一个
AuthorizationChecker
类的模拟,当调用
isgrated()
方法时,该类将返回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()
调用也不起作用。

您要模拟的方法被声明为最终方法,因此您不能按如下所述进行测试:

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

您可以查看部分解决方案


希望这个帮助

我能够通过模拟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 );

您好,您可以尝试模拟不是最终的AuthorizationCheckerInterface接口:取决于您需要做什么,通常将类定义为类接口的用法。您好Matteo,感谢您的回答和建议。我最终只是模仿了界面,效果很好。