Каков способ избежать того, что phpunit должен вызвать конструктор для макета? В противном случае мне понадобился бы mock-объект как аргумент конструктора, другой для этого и т. Д. Api выглядит так:
getMock($className, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE)
Я не работаю. Он все еще жалуется на аргумент конструктора, даже если $callOriginalConstructor
установлен в false.
У меня есть только один объект в конструкторе, и это инъекция зависимости. Поэтому я не думаю, что у меня проблемы с дизайном.
Вы можете использовать getMockBuilder
вместо просто getMock
:
$mock = $this->getMockBuilder('class_name') ->disableOriginalConstructor() ->getMock();
Подробнее см. Раздел «Испытательные пары» в документации PHPUnit .
Хотя вы можете это сделать, гораздо лучше не нужно. Вы можете реорганизовать свой код, поэтому вместо конкретного класса (с конструктором), который необходимо ввести, вы будете зависеть только от интерфейса. Это означает, что вы можете высмеять или заглушить интерфейс, не указав PHPUnit на изменение поведения конструктора.
Ну вот:
// Get a Mock Soap Client object to work with. $classToMock = 'SoapClient'; $methodsToMock = array('__getFunctions'); $mockConstructorParams = array('fake wsdl url', array()); $mockClassName = 'MyMockSoapClient'; $callMockConstructor = false; $mockSoapClient = $this->getMock($classToMock, $methodsToMock, $mockConstructorParams, $mockClassName, $callMockConstructor);
В качестве добавления я хотел приложить вызовы expects()
к моему издеваемому объекту, а затем вызвать конструктор. В PHPUnit 3.7.14 объект, который возвращается при вызове disableOriginalConstructor()
является в буквальном смысле объектом.
// Use a trick to create a new object of a class // without invoking its constructor. $object = unserialize( sprintf('O:%d:"%s":0:{}', strlen($className), $className)
К сожалению, в PHP 5.4 есть новый вариант, который они не используют:
ReflectionClass :: newInstanceWithoutConstructor
Поскольку это не было доступно, мне пришлось вручную отобразить класс, а затем вызвать конструктор.
$mock = $this->getMockBuilder('class_name') ->disableOriginalConstructor() ->getMock(); $mock->expect($this->once()) ->method('functionCallFromConstructor') ->with($this->equalTo('someValue')); $reflectedClass = new ReflectionClass('class_name'); $constructor = $reflectedClass->getConstructor(); $constructor->invoke($mock);
Обратите внимание: если functionCallFromConstruct
protected
, вам необходимо использовать setMethods()
чтобы защищенный метод был посмеян. Пример:
$mock->setMethods(array('functionCallFromConstructor'));
setMethods()
должен быть вызван перед вызовом expect()
. Лично я disableOriginalConstructor()
это после disableOriginalConstructor()
но перед getMock()
.
Возможно, вам нужно создать заглушку для передачи в качестве аргумента конструктора. Затем вы можете разбить эту цепочку издевательских объектов.
В качестве альтернативы вы можете добавить параметр в getMock, чтобы предотвратить вызов конструктора по умолчанию.
$mock = $this->getMock(class_name, methods = array(), args = array(), mockClassName = '', callOriginalConstructor = FALSE);
Тем не менее, я думаю, что ответ dave1010 выглядит лучше, это только ради полноты.
PHPUnit предназначен для вызова конструктора на издевающихся объектах; для предотвращения этого вам необходимо: