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

Posted

技术标签:

【中文标题】如何在 Mockery 中为受保护的属性存根公共设置方法【英文标题】:How to stub a public setter method for a protected property in Mockery 【发布时间】:2020-11-11 14:38:50 【问题描述】:

我想为我正在测试的同一类中的受保护属性存根公共设置方法 (setA()),但我收到此错误:

无法访问受保护的属性 Mockery_2_Foo::$a

我的目标只是对method1 进行单元测试,但该方法调用setA,所以我不确定如何刺出setA,因此它不会以任何方式干扰单元- method1 的测试结果。

class Foo 
    protected $a;
   
    public function setA($val)  
        $this->a =  $val * 2;
    
 
   
    public function method1($val)   
        $this->setA($val);
        return $val * 4;
   
   ............


/**
 * @coversDefaultClass Foo
 */
class FooTest 
 
    public function setUp(): void  
        $this->foo = Mockery::mock(Foo::class) 
            ->shouldAllowMockingProtectedMethods()
            ->makePartial();  
    
    /** 
     * @covers ::method1 
     */
    
    public function testMethod1() 
        $this->foo->shouldReceive('setA')
            ->set('a', 4);  
        $this->assertEquals(8, $this->foo->method1(2));  
    
    ..........
``

【问题讨论】:

【参考方案1】:

Mockery 只能设置公共属性(见docs)。

我真的不明白你想要做什么,但也许这只是因为你的简化示例。您可以创建一个匿名类来扩展 Foo 并添加所需的行为,而不是使用 Mockery:

class FooTest extends TestCase

    public function testMethod1()
    
        $foo = new class extends Foo 
            public function setA($val)
            
                $this->a = 4;
            
        ;

        self::assertEquals(8, $foo->method1(2));
    

【讨论】:

我的目标只是测试method1。但是那个方法调用setA,所以我正在寻找一种方法来刺出setA,这样它就不会以任何方式影响method1的单元测试。 在这种情况下,仅使用 $this->foo->shouldReceive('setA') (没有 ->set() 期望)是否也可以接受,或者您的解决方案是我应该运行此单元测试的唯一方法吗?谢谢 @Edville 从您给出的示例中,我想说method1 的目的是返回输入值乘以四。这就是我要测试的。我看不出有什么理由删除 setA,因为它不会以任何方式改变 method1 的结果。

以上是关于如何在 Mockery 中为受保护的属性存根公共设置方法的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 类中表示受保护的方法?

在 rspec 中为 API 规范存根protect_from_forgery

如何使用 Python 将文件压缩为受密码保护的存档

为啥继承的受保护运算符=()具有公共访问权限

如何在 WSO2IS 中为 PolicyEntitlementAdminService 生成存根

开放式办公数据库密码保护