Подтвердить что ты не робот

PHPUnit: методы заглушки undefined

Мне что-то не хватает. Я пытаюсь заглушить методы в классе в PHPUnit, но когда я вызываю метод на макет-объект, он сообщает мне, что метод undefined.

Пример класса для заглушки:

namespace MyApp;

class MyStubClass 
{
   public function mrMethod()
   {
     // doing stuff
   }   
}

Чтобы заглушить его, я пишу:

// specifying all getMock() args to disable calling of class __construct()
$stub = $this->getMock('MyStubClass', array(), array(), 'MockMyStubClass', false, false, false);
$stub->expects($this->any())
     ->method('mrMethod')
     ->will($this->returnValue('doing stuff'));

Но при вызове stubbed метода я получаю исключение:

$stub->mrMethod();
//PHP Fatal error:  Call to undefined method MockMyStubClass::mrMethod()

Я использую PHPUnit 3.4.3 с PHP 5.3.0.

Еще одна небольшая вещь, которую я заметил, заключалась в том, что если указание пространства имен в методе getMock() приводит к исключению загрузки класса из-за двойного пространства имен:

$stub = $this->getMock('MyApp\MyStubClass');
// Fatal error:  Class 'MyApp\MyApp\MyStubClass' not found

Это кажется мне довольно странным (и getmock() не будет принимать пространство имен с ведущей обратной косой чертой). Единственное, что я мог подумать, что это может быть связано с тем, что этот класс зарегистрирован на автозагрузчике?

Любые мысли?

4b9b3361

Ответ 1

Отвечая на мой собственный вопрос:

После некоторого разочарования, мне удалось заставить все работать. Я точно не знаю, в чем проблема, но обнаружил несколько вещей, которые могли бы помочь другим:

  • Убедитесь, что вы используете последнюю версию PHPUnit (3.4.6 на момент написания этой статьи).
  • Используйте полностью определенное пространство имен минус первая обратная косая черта.

    $this->getMock('MyApp\Widgets\WidgetFactory');
    

Часть моей проблемы заключалась в том, что PHPUnit создавал класс stub WidgetFactory, который на самом деле не выполнялся MyApp\Widgets\WidgetFactory. Можно было бы ожидать, что возникнет исключение, если вы попытаетесь заглушить несуществующий класс, но это не похоже на путаницу пространства имен.

Также существует вопрос о здесь, в котором предлагается использовать метод псевдонима класса следующим образом:

    class_alias('MyApp\Widgets\WidgetFactory', 'WidgetFactory');
    $this->getMock('WidgetFactory');

Хотя это временно решило мою проблему, я бы настоятельно советовал не использовать ее. class_alias() нельзя вызывать дважды для одного и того же псевдонима, не создавая исключения, что вызывает очевидную проблему, если используется в методе setup() или как часть генерации заглушки.

Ответ 2

У меня была аналогичная проблема, моя проблема заключалась в том, что путь, который я писал, был чем-то вроде MyApp\Widgets\WidgetFactory\MyStubClass, в то время как класс был примерно таким:

namespace MyApp;

class MyStubclass 
{
   public function mrMethod()
   {
     // doing stuff
   }   
}

Таким образом, не было прописного слова C в названии класса в пути