2015-06-16 2 views
5

Я пытаюсь создать свой первый тест phpunit и найти необходимость заглушить метод на интерфейсе IMailer.PHPUnit вызов неопределенного метода `Mock_x _ :: method()`

interface IMailer 
{ 
    public function send($to, $from, $cc, $subject, $body); 
    public function sent(); 
} 

    $mailer = $this->getMockBuilder(
     'IMailer', 
     array('send', 'sent'))->getMock(); 

    $mailer->method('send')->willRreturn(0); 

Однако я получаю

PHP Fatal error: 
    Call to undefined method Mock_Mailer_13fc0a04::method() 
    in ...Test.php on line 16 

а var_dump($mailer); результаты в

class Mock_IMailer_4c3e02a7#215 (1) { 
    private $__phpunit_invocationMocker => 
    NULL 
} 

Работа с дает ошибку Дито - кажется, что издевались объект не имеет каких-либо издеваться функциональность ...

Я запускаю phpunit 3.7.28 и php 5.5.9, на ящике ubuntu.

Почему? Как я могу это исправить?

ответ

5

Функция getMockBuilder принимает только параметр className как параметр. Правильный способ инициализировать имитировали методы объекта будет использовать функцию setMethods (см phpunit docs)

$mailer = $this->getMockBuilder('IMailer') 
     ->setMethods(array('send', 'sent')) 
     ->getMock(); 

Кроме того, вы, вероятно, хотите, чтобы иметь некоторое определение ожидает также, когда вы используете ваш фиктивный объект:

$mailer->expects($this->any()) 
     ->method('send') 
     ->willReturn(0); 

EDIT

Вышеупомянутое относится к новым версиям phpunit. Для phpunit 3.7.28 использование mock-объекта немного отличается (т. Е. Ожидается, что это будет обязательным, и willReturn пока недоступно). Для 3.7.28 версии вы должны изменить вторую часть к:

$mailer->expects($this->any()) 
     ->method('send') 
     ->will($this->returnValue(0)); 

Я рекомендовал бы обновить до более поздней версии PHPUnit, как это, кажется, довольно трудно найти в документации к этому гораздо более старого выпуска.

+0

Спасибо за исправление моей 'getMockBuilder' розарий. Однако «неопределенный метод» остается ... – xtofl

+0

Приведенный выше код работает без ошибок на phpunit 4.1.0.Вы пытались добавить вызов функции ожиданий ко второй части ('$ mailer-> expects-> method-> willReturn')? Не могли бы вы поделиться всем тестовым классом, который вы используете? Это может дать еще несколько подсказок к проблеме, с которой вы сталкиваетесь ... – ejuhjav

+1

Я думаю, что это должен быть принят ответ. -> setMethods и -> returnValue решил мою очень похожую проблему (тоже кажется, у меня есть старый phpunit) – Jimmmy

0

Альтернативное решение для любого, кто все еще использует старые версии PHPUnit, но по-прежнему хочет напрямую позвонить method(), является переопределение шаблона класса макета объекта по умолчанию.

Копия MockObject/Generator/mocked_class.tpl.dist, а также имя копии mocked_class.tpl. Затем, просто добавьте the code for the method() method к шаблону:

public function method() 
{ 
    $any = new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount; 
    $expects = $this->expects($any); 
    $args = func_get_args(); 
    return call_user_func_array(array($expects, 'method'), $args); 
} 

Это позволит вам звонить $mock->method() непосредственно. Тем не менее, вам необходимо использовать ->will($this->returnValue(0)) вместо ->willReturn(0). Чтобы сделать это, вам нужно ввести пользовательский вызов строитель и вызова насмешник:

class My_MockObject_Builder_InvocationMocker 
    extends PHPUnit_Framework_MockObject_Builder_InvocationMocker { 

    public function willReturn($value) { 
     return $this->will(new PHPUnit_Framework_MockObject_Stub_Return($value)); 
    } 
} 

class My_MockObject_InvocationMocker 
    extends PHPUnit_Framework_MockObject_InvocationMocker { 

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher) { 
     return new My_MockObject_Builder_InvocationMocker($this, $matcher); 
    } 
} 

и обновить шаблон снова, чтобы использовать My_MockObject_InvocationMocker вместо PHPUnit_Framework_MockObject_InvocationMocker.

Полный шаблон будет выглядеть следующим образом:

{prologue}{class_declaration} 
{ 
    protected static $staticInvocationMocker; 
    protected $invocationMocker; 

{clone}{mocked_methods} 
    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher) 
    { 
     return $this->__phpunit_getInvocationMocker()->expects($matcher); 
    } 

    public function method() 
    { 
     $any = new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount; 
     $expects = $this->expects($any); 
     $args = func_get_args(); 
     return call_user_func_array(array($expects, 'method'), $args); 
    } 

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher) 
    { 
     return self::__phpunit_getStaticInvocationMocker()->expects($matcher); 
    } 

    public function __phpunit_getInvocationMocker() 
    { 
     if ($this->invocationMocker === NULL) { 
      $this->invocationMocker = new My_MockObject_InvocationMocker; 
     } 

     return $this->invocationMocker; 
    } 

    public static function __phpunit_getStaticInvocationMocker() 
    { 
     if (self::$staticInvocationMocker === NULL) { 
      self::$staticInvocationMocker = new My_MockObject_InvocationMocker; 
     } 

     return self::$staticInvocationMocker; 
    } 

    public function __phpunit_hasMatchers() 
    { 
     return self::__phpunit_getStaticInvocationMocker()->hasMatchers() || 
       $this->__phpunit_getInvocationMocker()->hasMatchers(); 
    } 

    public function __phpunit_verify() 
    { 
     self::__phpunit_getStaticInvocationMocker()->verify(); 
     $this->__phpunit_getInvocationMocker()->verify(); 
    } 

    public function __phpunit_cleanup() 
    { 
     self::$staticInvocationMocker = NULL; 
     $this->invocationMocker  = NULL; 
    } 
}{epilogue} 
Смежные вопросы