PHPUnit - 模拟特征

时间:2016-10-18 21:53:56

标签: php phpunit prophecy

我有一个由多个类使用的特征,即

class SomeClass
{
     use TimeoutTrait;

     function handle() {
         $this->traitFunction()    // can this be mocked?
     }
}

PHP单元能够模拟traitFunction()?。

提前感谢您的帮助。

问候

3 个答案:

答案 0 :(得分:3)

Traits是代码容器,代码是" copy-pasted"通过编译器进入您想要使用它的类,从而使它可以在全世界重复使用。

通常,单元测试中的特征函数没有什么特别之处。当类被实例化时, trait函数不会对可以复制粘贴的函数产生任何影响,它们将被写入类中的特征。

所以,不要犹豫模仿你的特质函数,就像在课堂上定义的任何其他常规函数一样。

答案 1 :(得分:2)

当您使用PHPUnit模拟一个类时,它会扩展该类并覆盖您使用替换方法进行模拟的方法。所以在你的情况下,它看起来像这样:

$sut = $this->getMockBuilder('SomeClass')
    ->setMethods(['traitFunction'])
    ->getMock();

$sut->expects($this->once())
    ->method('traitFunction');

$sut->handle();

虽然这样做不是一个好主意,IMO。您正在指定您的课程应该如何做而不是应该做什么。如果你的特质提供的方法很复杂,足以保证你自己的类,你觉得你需要嘲笑它。使其成为一个独立的类,并使用strategy pattern传递行为。

你的班级会喜欢这个:

Class SomeClass {
    private $handler;

    public function __construct(ClassFormerlyATrait $handler) {
        $this->handler = $handler;
    }

    public function handler() {
        $this->handler->traitFunction();
    }
}

Class ClassFormerlyATrait {
    public function traitFunction() {
     // Does whatever the trait did.
    }
}

这使您的设计更复杂,但您现在可以根据更改调整您的课程。例如,在某些情况下,您需要traitFunction做一些稍微不同的事情。您可以使用新功能扩展ClassFormerlyATrait并将其传递给SomeClass,而不必担心破坏任何现有功能。

答案 2 :(得分:0)

最简单的方法是模拟父类,然后对特征进行单元测试。或者你可以创建一个特定的类来实现特征,仅用于单元测试,但是假设你的特性不会做任何与父母交互的事情,反之亦然。