У меня есть черта, которая используется несколькими классами, т.е.
class SomeClass
{
use TimeoutTrait;
function handle() {
$this->traitFunction() // can this be mocked?
}
}
Модуль PHP способен издеваться над traitFunction ()?
Заранее спасибо за помощь.
Привет
Черты контейнеры кода какой код «копируется» компилятором в класс, в котором вы хотите его использовать, что делает его многократно используемым во всем мире.
Как правило, в модульных тестах нет ничего особенного с функциями черт. когда класс создается функции черты не имеют никакого значения из функций, которые можно скопировать прямо, они написаны чертой внутри вашего класса.
Так что не стесняйтесь высмеивать вашу функцию черты так же, как и любую другую обычную функцию определяется внутри класса.
Когда вы макетируете класс с помощью PHPUnit, он расширяет класс и переопределяет методы, которые вы насмехаетесь, с заменой. Так что в вашем случае это будет выглядеть так:
$sut = $this->getMockBuilder('SomeClass')
->setMethods(['traitFunction'])
->getMock();
$sut->expects($this->once())
->method('traitFunction');
$sut->handle();
Хотя делать это не очень хорошая идея, ИМО. Вы указываете, как ваш класс должен что-то делать, а не то, что он должен делать. Если метод, который обеспечивает ваша черта, достаточно сложен, чтобы гарантировать свой собственный класс, то вы чувствуете, что вам нужно его высмеивать. Сделайте это отдельным классом и используйте шаблон стратегии передать в своем поведении.
Ваш класс хотел бы это:
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, не беспокоясь о нарушении любой существующей функциональности.
Самый простой способ — смоделировать родительский класс, а затем выполнить свои модульные тесты на эту черту. Или вы можете создать специальный класс для реализации черты, исключительно для модульного тестирования, но это предполагает, что ваша черта не делает ничего, что взаимодействует с родителем или наоборот.