phpunit избежать аргументов конструктора для mock

Каков способ избежать того, что 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 предназначен для вызова конструктора на издевающихся объектах; для предотвращения этого вам необходимо:

  1. Внедрить макет объекта в зависимость от объекта, с которым вы сталкиваетесь
  2. Создайте тестовый класс, который расширяет класс, который вы пытаетесь вызвать, который не вызывает родительский конструктор