Как частично издеваться над классом с помощью Mockery?

У меня этот класс:

class PagSeguro {

 public function pay()
 {
 if ( ! $this->checkAllData() )
 {
 return false;
 }

 return $this->buildPaymentURL();
 }

 private function checkAllData()
 {
 return true;
 }

 private function buildPaymentURL()
 {
 echo "not cool!\n\n";

 return true;
 }

}

И этот тест для него:

public function testPagSeguroPaymentData()
{
 $m = m::mock('PagSeguro[buildPaymentURL]');

 $m->shouldReceive('buildPaymentURL')
 ->once()
 ->andReturn('http://');

 $this->assertEquals($m->pay(), 'http://');
}

Если я var_dump ($ m), я вижу смеющийся метод:

'buildPaymentURL' =>
 class Mockery\ExpectationDirector#1507 (5) {
 protected $_name =>
 string(15) "buildPaymentURL"
 protected $_mock =>
 ...

 protected $_expectations =>
 array(1) {
 ...
 }
 protected $_expectedOrder =>
 NULL
 protected $_defaults =>
 array(0) {
 ...
 }
 }
 }

Но когда тест выполняется, он вызывает не издеваемую, а настоящую. Если я не переименую его

private function buildPaymentURL_RENAMED() {}

И тогда я получаю зеленый цвет.

Кто-нибудь может показать мне правильный способ сделать эти частичные макеты с помощью Mockery?

1 ответ

Я думаю, что вы не можете иметь этот метод быть private, потому что очень много времени ввода кода вашего реального объекта, любой вызов $this->buildPaymentURL должен закончиться в этом режиме реального частного метода.

Сделайте его защищенным. Таким образом, макет может расширить ваш класс и перезаписать функцию.

С другой стороны, у меня всегда есть плохое чувство, если есть необходимость в таких частичных насмешках. Они, скорее всего, являются признаком плохого дизайна. Кажется, что этот частный метод скорее должен содержаться в собственном объекте, который имеет дело исключительно с созданием URL (и может быть протестирован отдельно), и этот класс, который вы тестируете, должен только получить полный макет этого нового класса.

licensed under cc by-sa 3.0 with attribution.