【问题标题】:PHPUnit mock - call parent __get/__set/__issetPHPUnit mock - 调用父 __get/__set/__isset
【发布时间】:2020-01-25 10:47:45
【问题描述】:

我试图模拟一个继承了魔法方法的类,但它们没有被实现,我不知道如何修复它。 代码如下:

<?php
use PHPUnit\Framework\TestCase;

class AnnoyingTestCase extends TestCase
{
    public function testNoAttributes()
    {
        $mock = $this->createMock(Child::class);
        $mock->attribute = 'value';

        $this->assertEquals($mock->attribute, null);
    }
}

class Base
{
    private $attributes = [];

    public function __set($name, $value)
    {
        $this->attributes[$name] = $value;
    }

    public function __get($name)
    {
        return $this->attributes[$name] ?? null;
    }

    public function __isset($name)
    {
        return isset($this->attributes[$name]);
    }
}

class Child extends Base
{
}

我希望 $mock-&gt;attribute 具有我分配给它的值,但它没有,因为 __set 没有被调用。

如果我尝试使用-&gt;addMethods(['__get', '__set']),则会引发异常:Trying to set mock method "__get" with addMethods(), but it exists in class "Child". Use onlyMethods() for methods that exist in the class.。 然而在__set 方法中添加var_dump 表明它没有被调用。

我该怎么做才能让它拥有这些方法? 请注意,我不打算实现我自己的等效方法,我希望模拟具有这些原始方法。

【问题讨论】:

  • 模拟的全部意义在于它不采用类的任何现有行为,而是将所有函数留空,以便您可以决定它们在特定情况下将返回什么。你想在这个测试中测试什么?如果您想测试子类的魔术方法,那么您应该创建该类的实际实例,然后断言该类具有预期值。现在好像你正在测试一个模拟,这没有多大意义。
  • @DirkScholten 我正在测试使用与上述Child 类等效的类的代码,并且希望避免编写样板代码。

标签: php mocking phpunit magic-methods


【解决方案1】:

找到了解决这个确切问题的方法,但它可能弊大于利。 以下代码有效:

$mock = $this->getMockBuilder(Child::class)
    ->enableProxyingToOriginalMethods()
    ->getMock();

但是,这会代理所有原始方法调用,并且无法缩小要代理的方法的范围。最大的——可能被破坏的构造函数调用——在这里描述:PHPUnit - MockBuilder::enableProxyingToOriginalMethods() breaks when original constructor calls public method

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 2015-04-04
    • 2016-06-09
    • 1970-01-01
    相关资源
    最近更新 更多