Undefined метод на 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:
Неустранимая ошибка: вызов метода undefinedMock_ConfigurationInterface_21e9dccf:: GetClass().
$converter = new ReportEventParamConverter();
$this->assertFalse($converter->supports($mock));
Ответы
Ответ 1
Это потому, что в 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'));
Ответ 2
Ответ Киприана помог мне, но там есть информация, о которой нужно знать. Вы можете высмеивать классы, которых не существует, и PHPUnit не будет жаловаться. Таким образом, вы могли бы сделать
$mock = $this->getMock('SomeClassThatDoesntExistOrIsMisspelledOrPerhapsYouForgotToRequire');
Это означает, что если ConfigurationInterface
не существует в этой точке во время выполнения, вы все равно получите сообщение типа
Неустранимая ошибка: вызов метода undefinedMock_ConfigurationInterface_21e9dccf:: GetClass().
Если вы уверены, что метод действительно существует в классе, то вероятная проблема заключается в том, что сам класс не существует (потому что вы его не требуете, или вы его опечалили и т.д.).
OP использует интерфейс. Имейте в виду, что вы должны вызвать getMock
, не указав список методов для переопределения, или если вы это сделаете, вы должны либо пройти array()
, либо передать ВСЕ имена методов, либо вы получите сообщение об ошибке, как показано ниже:
PHP Неустранимая ошибка: класс Mock_HttpRequest_a7aa9ffd содержит 4 тега методов и поэтому должны быть объявлены абстрактными или реализовать остальные методы (HttpRequest:: setOption, HttpRequest:: execute, HttpRequest:: getInfo,...)
Ответ 3
Предупреждение Tyler Collier справедливо, но не содержит фрагмента кода о том, как его кодировать. Обратите внимание, что это очень неприятно, и вы должны исправить интерфейс. С этим предупреждением добавлено:
$methods = array_map(function (\ReflectionMethod $m) { return $m->getName();}, (new \ReflectionClass($interface))->getMethods());
$methods[] = $missing_method;
$mock = $this->getMock($interface, $methods);