用嘲弄来嘲弄 trait 方法

Posted

技术标签:

【中文标题】用嘲弄来嘲弄 trait 方法【英文标题】:Mocking trait methods with mockery 【发布时间】:2017-09-01 16:57:43 【问题描述】:

我有一个特点:

trait A 
    function foo() 
        ...
    

还有一个使用这种特性的类:

class B 
    use A 
        foo as traitFoo;
    

    function foo() 
        $intermediate = $this->traitFoo();
        ...
    

我想测试类的 foo() 方法并想模拟(使用 Mockery)特征的 foo() 方法的行为。我尝试使用部分和嘲笑traitFoo() 喜欢:

$mock = Mockery::mock(new B());
$mock->shouldReceive('traitFoo')->andReturn($intermediate);

但它不起作用。

可以这样做吗?有替代方法吗?我想测试 B::foo() 将其与 trait 的 foo() 实现隔离开来。

提前致谢。

【问题讨论】:

如何“它不起作用”。确切地?你在测试中称它为$mock->foo() 吗?一般来说,mock CUT 并不是很推荐。 是的,我将其称为$mock->foo()。它不起作用,因为调用的是真正的特征方法而不是模拟方法。我使用模拟作为 CUT 的代理,并且能够在不依赖在其他地方测试的特征的情况下隔离方法测试。 【参考方案1】:

您使用的代理模拟来自模拟外部的代理调用,因此无法模拟 $this->... 类中的内部调用。

如果你没有 final 方法,你仍然可以使用普通的部分模拟或被动的部分模拟,它扩展了模拟类,并且没有这样的限制:

$mock = Mockery::mock(B::class)->makePartial();
$mock->shouldReceive('traitFoo')->andReturn($intermediate);
$mock->foo();

更新:

非模拟特征函数的完整示例:

use Mockery as m;

trait A

    function foo()
    
        return 'a';
    

    function bar()
    
        return 'd';
    


class B

    use A 
        foo as traitFoo;
        bar as traitBar;
    

    function foo()
    
        $intermediate = $this->traitFoo();
        return "b$intermediate" . $this->traitBar();
    



class BTest extends \phpUnit_Framework_TestCase


    public function testMe()
    
        $mock = m::mock(B::class)->makePartial();
        $mock->shouldReceive('traitFoo')->andReturn('c');
        $this->assertEquals('bcd', $mock->foo());
    

【讨论】:

我试过这个,但其他对特征方法的调用停止工作。似乎模拟类不知道该特征的使用。 你需要更新问题。 “停止工作”是相当模糊的。请参阅我的更新以获取非模拟特征函数仍然有效的示例。 我找到了问题的根源。我的方法是受保护的,并且嘲讽说“不能被模拟,因为它是受保护的方法,并且这个模拟不允许模拟受保护的方法”。我卡住了吗? 我有点迷失在更新中。你能用一个重现问题的例子来编辑你的问题吗?如果只是保护traitFoo,则需要在创建mock时加上->shouldAllowMockingProtectedMethods() ->shouldAllowMockingProtectedMethods() 一起工作!谢谢!我在文档中的任何地方都找不到对此方法的引用...它没有记录吗?

以上是关于用嘲弄来嘲弄 trait 方法的主要内容,如果未能解决你的问题,请参考以下文章

嘲弄用 andReturn 返回新对象

嘲弄“应该接收”但方法不存在

嘲弄重载类缺少方法

Laravel 的嘲弄不会模拟方法

不能用嘲弄 phpunit 来模拟对象

闭包内的嘲弄模拟方法