【问题标题】:Mocked class: methods hinting模拟类:方法提示
【发布时间】:2015-12-19 02:30:32
【问题描述】:

我有以下设置:我正在使用 PHPUnit 模拟非抽象类,但不是所有方法。因此,非模拟方法仍然作为对模拟中真实方法的调用存在。

问题是:如何暗示这些方法是可用的(当然,有正确的签名)?

我会详细说明一下。班级样本:

class RealClass
{
    public function callApi(Api $api) {}

    public function doStuff(Foo $foo, Bar $bar) {}
}

现在我在做测试:

/** @var  \PHPUnit_Framework_MockObject_MockObject $mock */
$mock = $this->getMock('\RealClass', ['callApi']);

这将仅为callApi() 创建模拟,但如果在测试中我这样做:

$mock->doStuff($foo, $bar);

我的 PHPStorm 显然找不到该方法,并认为这是一个错误。我如何指出 doStuff() 方法存在并且需要正确的参数?

@method 似乎只在类定义中工作。我试着和@see 玩了一下,但无法解决这个问题。此外,理想的解决方案是允许在 return 语句中指定提示的解决方案,因为我可能希望从测试助手方法返回模拟。

“便宜的作弊”是暗示与原来的类,但我不想这样做,从那以后我就会失去意义——这是模拟的,哪个不是。这一点尤其重要,因为我使用助手来构建注入模拟的复杂实体。

【问题讨论】:

    标签: mocking phpunit phpstorm phpdoc


    【解决方案1】:

    您应该将模拟提示为 MockObjectRealClass 的实例,因此您会得到类似的内容:

    /** @var \RealClass|\PHPUnit_Framework_MockObject_MockObject $mock */
    $mock = $this->getMock('\RealClass', ['callApi']);
    

    现在您告诉 PhpStorm $mock 可以是 PHPUnit MockObject RealClass 实例,它将接受/自动完成任一类的方法。

    此外(这只是一个友好的建议,完全没有必要),您可以使用 use 关键字将类导入到您的测试类中,这样您的提示就会变得更具可读性:

    <?php
    
    use \RealClass;
    use \PHPUnit_Framework_MockObject_MockObject as MockObject;
    
    class YourTestClass
    {
        public function yourTest()
        {
            // Because of the use statements (and the "as" alias rule) you can now:
            /** @var RealClass|MockObject $mock */
            $mock = $this->getMock('RealClass', ['callApi']);
        }
    }
    

    【讨论】:

    • 但是话又说回来 - 我无法区分它是否在某个地方是模拟的。这一点很重要,因为当我构建存根提供程序时,我需要在某条线上知道——这些东西是否被模拟。现在我只是用命名来区分(命名变量又名$fooMock,$barMock)。所以如果是这样的话 - 那么我会用原始课程来暗示它,就是这样。感谢您的回答,无论如何+1
    • 当像这样使用mock时,只有callApi方法被mock出类,其他方法会从真实类中使用,所以你不要mock整个类,只mock方法(因此应该始终知道您正在处理的是哪一个)。除非我误解了,否则最好打开一个单独的问题,提供更多详细信息。
    • 是的,我知道。但是想象一下这种情况 - 你需要区分某些 $something 是否是模拟的。 $something 是从某个助手返回的,我暗示了 @return RealClass|MockObject。现在 - 怎么说,是模拟还是不模拟?是的,它会从两者中组装方法,但实体本身的身份并不清楚。这就是我在答案中指出的——这就是我现在所缺乏的。
    • 您可以使用instanceof 来实现这一点。喜欢if ($mock instanceof MockObject) { // It's the mock }if ($mock instanceof RealClass) { // it's the real class }
    • Ehm.. no :) 因为那样我就把它命名为“$mockSomething”
    猜你喜欢
    • 2016-04-21
    • 2011-03-14
    • 2011-02-17
    • 2019-07-05
    • 2021-12-08
    • 1970-01-01
    • 2018-10-06
    • 2015-11-27
    • 1970-01-01
    相关资源
    最近更新 更多