4

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

class SomeClass
{
     use TimeoutTrait;

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

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

在此先感谢您的帮助。

问候

4

3 回答 3

6

特征是代码容器,编译器将代码“复制粘贴”到您想要使用的类中,从而使其在世界范围内可重用。

一般来说,单元测试中的特征函数没有什么特别的关系,bec。当类被实例化时,特征函数与可以复制粘贴的函数没有任何区别,它们是在类中的特征中编写的。

因此,不要犹豫,像在类中定义的任何其他常规函数一样模拟您的特征函数。

于 2016-10-20T18:24:06.220 回答
2

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

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

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

$sut->handle();

虽然这样做不是一个好主意,IMO。您正在指定您的班级应该如何做某事,而不是它应该做什么。如果您的 trait 提供的方法足够复杂以保证它自己的类,您觉得需要模拟它。使其成为一个独立的类,并使用策略模式来传递行为。

你的班级会这样:

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 而不必担心破坏任何现有功能。

于 2016-10-20T18:13:18.260 回答
0

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

于 2016-10-18T22:05:11.070 回答