【问题标题】:phpunit mock - method does not existphpunit mock - 方法不存在
【发布时间】:2017-01-28 19:03:52
【问题描述】:

我最近在基于 CakePhp 3.x 的应用程序的 IntegrationTestCase 中将 PHPunit 从 5.3 更新到 5.5。而且我不明白如何更新我的模拟生成脚本。

最初我是这样创建我的模拟的:

$stub = $this->getMock('SomeClass', array('execute'));
$stub->method('execute')
     ->will($this->returnValue($this->returnUrl));

更改为 PHPUnit 5.5 后,我收到以下警告:

PHPUnit_Framework_TestCase::getMock() is deprecated,
use PHPUnit_Framework_TestCase::createMock()
or PHPUnit_Framework_TestCase::getMockBuilder() instead

为了修复这个警告,我将模拟生成更改为:

$stub = $this->getMockBuilder('SomeClass', array('execute'))->getMock();
$stub->method('execute')
     ->will($this->returnValue($this->returnUrl));```

现在我在运行测试时收到以下错误消息:

exception 'PHPUnit_Framework_MockObject_RuntimeException' 
with message 'Trying to configure method "execute" which cannot be
configured because it does not exist, has not been specified, 
is final, or is static'

任何人都知道,如何避免这个错误?谢谢。

【问题讨论】:

  • 可以发一下execute方法的代码吗?

标签: php unit-testing cakephp phpunit cakephp-3.0


【解决方案1】:

PHPUnit_Framework_TestCase::getMockBuilder() 只接受一 (1) 个参数,即类名。要模拟的方法将通过返回的模拟构建器对象setMethods() 方法来定义。

$stub = $this
    ->getMockBuilder('SomeClass')
    ->setMethods(['execute'])
    ->getMock();

另见

【讨论】:

  • 谢谢,就是这样。我应该使用 setMethods 而不是尝试在 getMockBuilder() 方法中传递一组方法名称作为第二个参数。
  • 仅供参考,setMethods() 已弃用,应替换为 onlyMethods()
  • @GordonM 没错,但 CakePHP 3.x 默认需要 PHPUnit 6.x 最晚,onlyMethods() 尚不存在。我不确定 3.x 是否与 PhpUnit 8+ 兼容?
【解决方案2】:

首先,这只是

$stub = $this->getMockBuilder('SomeClass')->getMock();

第二,错误指出方法execute确实存在于你的类SomeClass中。

所以,检查它是否真的存在,它是public 而不是final

如果一切正常,检查一个完整的类名,如果它是真实的并且指定了正确的命名空间。

为避免类名出现愚蠢的错误,最好使用以下语法:

$stub = $this->getMockBuilder(SomeClass::class)->getMock();

在这种情况下,如果 SomeClass 不存在或命名空间丢失,你会得到一个明确的错误。

【讨论】:

  • 谢谢,问题是我没有使用 setMethods() 函数(见 ndm 的回答)。
  • 这不是必需的步骤。原班有这个方法吗?
  • 是的,我在我的原始类中有它,我的测试期望调用“执行”(参见我的问题中的代码示例)。
  • @DmitryMalyshenko 如果方法不公开,则需要。
  • 如果不公开,被测类如何使用?
【解决方案3】:

当我再次遇到这个问题时,我将把这个作为自己的答案:

模拟的方法可能不是私有的。

【讨论】:

    【解决方案4】:

    也许,您模拟的类中不存在该方法。

    【讨论】:

    • 模拟中缺少该方法(请参阅 ndm 接受的答案和我的解决方案评论)
    • 我遇到了同样的问题,然后我发现我的类不包含该方法,所以我提出这个解决方案以某种方式解决同样的问题。
    • 知道了,可能对其他人有帮助
    【解决方案5】:

    上层消息的补充:拆分模拟方法声明

    而不是这个:

    $mock
        ->method('persist')
           ->with($this->isInstanceOf(Bucket::class))
           ->willReturnSelf()
        ->method('save')
           ->willReturnSelf()
    ;
    

    使用这个:

    $mock
        ->method('persist')
            ->willReturnSelf()
    ;
    
    $mock
       ->method('save')
           ->willReturnSelf()
    ;
    

    【讨论】:

      猜你喜欢
      • 2015-10-27
      • 2011-03-23
      • 2016-01-05
      • 1970-01-01
      • 2011-08-24
      • 2015-04-04
      • 1970-01-01
      • 2014-02-08
      • 2012-11-17
      相关资源
      最近更新 更多