Неопределенный метод для mock-объекта, реализующего данный интерфейс в PHPUnit?

Я новичок в модульном тестировании и PHPUnit.

Мне нужен макет, на котором у меня есть полный контроль, реализующий интерфейс ConfigurationInterface . Объектом тестирования является объект ReportEventParamConverter и тест должен проверять взаимодействие между моим объектом и интерфейсом.

Объект ReportEventParamConverter (здесь упрощенный):

 class ReportEventParamConverter implements ParamConverterInterface { /** * @param Request $request * @param ConfigurationInterface $configuration */ function apply(Request $request, ConfigurationInterface $configuration) { $request->attributes->set($configuration->getName(), $reportEvent); } /** * @param ConfigurationInterface $configuration * @return bool */ function supports(ConfigurationInterface $configuration) { return 'My\Namespaced\Class' === $configuration->getClass(); } } 

И так я пытаюсь высмеять интерфейс:

 $cls = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface'; $mock = $this->getMock($mockCls); 

Мне нужно смоделировать возвращаемые значения для двух методов: getClass() и getName() . Например:

 $mock->expects($this->any()) ->method('getClass') ->will($this->returnValue('Some\Other\Class')) ; 

Когда я создаю новый ReportEventParamConverter и test supports() , я получаю следующую ошибку PHPUnit:

Неустранимая ошибка: вызов неопределенного метода Mock_ConfigurationInterface_21e9dccf :: getClass ().

 $converter = new ReportEventParamConverter(); $this->assertFalse($converter->supports($mock)); 

Это связано с тем, что в ConfigurationInterface нет объявления метода getClass. Единственное объявление в этом интерфейсе – метод getAliasName.

Все, что вам нужно, это рассказать о том, какие методы вы будете заглушить:

 $cls = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface'; $mock = $this->getMock($mockCls, array('getClass', 'getAliasName')); 

Обратите внимание, что нет объявления «getClass», но вы также можете заглушить и выпустить не существующий метод. Поэтому вы можете издеваться над этим:

 $mock->expects($this->any()) ->method('getClass') ->will($this->returnValue('Some\Other\Class')); 

Но в добавлении вам нужно издеваться над методом getAliasName, а также в том, что это метод интерфейса или абстрактный, и он должен быть «реализован». Например.:

 $mock->expects($this->any()) ->method('getAliasName') ->will($this->returnValue('SomeValue')); 

Ответ Киприана помог мне, но есть информация, о которой нужно знать. Вы можете высмеивать классы, которых не существует, и PHPUnit не будет жаловаться. Таким образом, вы могли бы сделать

 $mock = $this->getMock('SomeClassThatDoesntExistOrIsMisspelledOrPerhapsYouForgotToRequire'); 

Это означает, что если ConfigurationInterface не существует в этой точке во время выполнения, вы все равно получите сообщение типа

Неустранимая ошибка: вызов неопределенного метода Mock_ConfigurationInterface_21e9dccf :: getClass ().

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


OP использует интерфейс . Имейте в getMock что вы должны вызвать getMock не указав список методов для переопределения, или если вы это сделаете, вы должны либо передать array() , либо передать ВСЕ имена методов, либо вы получите ошибку, такую ​​как:

PHP Неустранимая ошибка: класс Mock_HttpRequest_a7aa9ffd содержит 4 абстрактных метода и поэтому должен быть объявлен абстрактным или реализовать остальные методы (HttpRequest :: setOption, HttpRequest :: execute, HttpRequest :: getInfo, …)

Предупреждение Тайлера Кольера справедливо, но не содержит фрагмента кода о том, как его кодировать. Обратите внимание, что это очень неприятно, и вы должны исправить интерфейс. С этим предупреждением добавлено:

 $methods = array_map(function (\ReflectionMethod $m) { return $m->getName();}, (new \ReflectionClass($interface))->getMethods()); $methods[] = $missing_method; $mock = $this->getMock($interface, $methods);