【问题标题】:How do I prevent the original method being called when mocking a class with PHPUnit?使用 PHPUnit 模拟类时如何防止调用原始方法?
【发布时间】:2016-06-20 10:47:14
【问题描述】:

根据我对 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'));

用 null 或空数组替换 setMethods() 的参数,或者完全删除调用,没有效果。也不会删除 expects()with() 调用。

【问题讨论】:

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

标签: php unit-testing phpunit


【解决方案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 );

【讨论】:

    【解决方案2】:

    您要模拟的方法被声明为最终方法,因此您不能像in the doc 所述那样测试加倍:

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

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

    希望有帮助

    【讨论】:

      猜你喜欢
      • 2014-10-17
      • 2020-11-15
      • 1970-01-01
      • 2020-01-04
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      • 2012-06-12
      相关资源
      最近更新 更多