是否可以模拟受保护的属性和方法

Posted

技术标签:

【中文标题】是否可以模拟受保护的属性和方法【英文标题】:Is it possible to mock protected properties and methods 【发布时间】:2015-11-05 20:40:28 【问题描述】:

是否可以使用 php Mockery 模拟受保护的属性?

我有一个带有方法的类,我将其命名为 `a,它对从同一类的受保护属性中检索到的数组执行一些魔法。

该受保护属性由同一类中的另一个方法 b 填充。

我想通过模拟受保护的属性来测试方法a,这样我就不必首先对方法b 进行分类。

那么这可能吗?如果不是,我应该重构我的代码吗?还是有其他方法(考虑最佳实践)。

【问题讨论】:

尝试使用反射 我(当然)做了谷歌,这确实是第一件事。但这感觉有点“骇人听闻”。我也想知道如何将它与部分模拟混合。 如果感觉很骇人,那么重构你的代码。我不完全确定你想做什么,但反射通常是当你不知道类属性是什么时动态读取它们的方法。 如果您想模拟私有或受保护的方法,而您的代码看起来很糟糕,请尝试重构它。 phpunit - mockbuilder - set mock object internal property的可能重复 【参考方案1】:

有时你的代码很好,你认为没有理由改变你的代码来促进测试(我认为这是一个很好的理由),我所做的是在我的对象中使用反射,你甚至可以有一个助手方法如下:

class MockingHelpers

    public static function mockProperty($object, string $propertyName, $value)
    
        $reflectionClass = new \ReflectionClass($object);

        $property = $reflectionClass->getProperty($propertyName);
        $property->setAccessible(true);
        $property->setValue($object, $value);
        $property->setAccessible(false);
    

请注意,可访问性仅应用于反射上下文,因此不会造成任何损坏。

这不是完美的解决方案,有时您的代码可能确实存在问题,但这可以帮助您!

【讨论】:

【参考方案2】:

可以模拟受保护的方法,但正如一些人指出的那样,如果您觉得需要模拟这些方法,您可能需要重构您的代码。

如果你确实想模拟受保护的方法,你可以按照下面的例子来做:

$myMock = Mockery::mock('myClass')->shouldAllowMockingProtectedMethods();

使用这个模拟,就可以像模拟公共方法一样模拟受保护的方法。

【讨论】:

这种方法适用于受保护的方法,但不适用于受保护的属性

以上是关于是否可以模拟受保护的属性和方法的主要内容,如果未能解决你的问题,请参考以下文章

特征可以具有具有私有和受保护可见性的属性和方法吗?特质可以有构造函数、析构函数和类常量吗?

PHP 从静态方法访问对象的受保护属性

json_encode类时丢失私有属性和受保护属性处理方法

ES6 类中的受保护属性(使用符号?)

在 Objective-C 中完成受保护属性的解决方法

如何在 Mockery 中为受保护的属性存根公共设置方法