tutorial - phpunit evitar los argumentos del constructor para simular
phpunit tutorial español (6)
Alternativamente, podría agregar un parámetro a getMock para evitar la llamada del constructor predeterminado.
$mock = $this->getMock(class_name, methods = array(), args = array(),
mockClassName = '''', callOriginalConstructor = FALSE);
Aún así, creo que la respuesta de dave1010 parece más bonita, esto es solo por el bien de la compleción.
¿Cuál es la forma de evitar que phpunit tenga que llamar al constructor para obtener un objeto simulado? De lo contrario, necesitaría un objeto falso como argumento de constructor, otro para eso, etc. La API parece ser así:
getMock($className, $methods = array(), array $arguments = array(),
$mockClassName = '''', $callOriginalConstructor = TRUE,
$callOriginalClone = TRUE, $callAutoload = TRUE)
No consigo que funcione. Todavía se queja del argumento constructor, incluso con $callOriginalConstructor
establecido en falso.
Solo tengo un objeto en el constructor y es una inyección de dependencia. Entonces no creo que tenga un problema de diseño allí.
Aqui tienes:
// 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);
Como apéndice, quería adjuntar llamadas expects()
a mi objeto simulado y luego llamar al constructor. En PHPUnit 3.7.14, el objeto que se devuelve al llamar a disableOriginalConstructor()
es literalmente un objeto.
// 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)
Desafortunadamente, en PHP 5.4 hay una nueva opción que no están utilizando:
ReflectionClass::newInstanceWithoutConstructor
Como esto no estaba disponible, tuve que reflejar manualmente la clase y luego invocar el constructor.
$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);
Tenga en cuenta que si functionCallFromConstruct
está protected
, debe usar setMethods()
para que se setMethods()
el método protegido. Ejemplo:
$mock->setMethods(array(''functionCallFromConstructor''));
setMethods()
debe setMethods()
antes de la llamada a expect()
. Personalmente, disableOriginalConstructor()
esto después de disableOriginalConstructor()
pero antes de getMock()
.
PHPUnit está diseñado para llamar al constructor en objetos burlados; Para evitar esto, debe hacer lo siguiente:
- Inyecta un objeto simulado como una dependencia en el objeto con el que estás teniendo problemas para burlarte
- Cree una clase de prueba que amplíe la clase a la que intenta llamar y que no llame al constructor padre
Puede usar getMockBuilder
lugar de solo getMock
:
$mock = $this->getMockBuilder(''class_name'')
->disableOriginalConstructor()
->getMock();
Consulte la sección sobre "Dobles de prueba" en la documentación de PHPUnit para más detalles.
Aunque puede hacer esto, es mucho mejor no necesitarlo. Puedes refactorizar tu código para que, en lugar de una clase concreta (con un constructor) que deba ser inyectada, solo dependas de una interfaz. Esto significa que puede simular o resguardar la interfaz sin tener que decirle a PHPUnit que modifique el comportamiento del constructor.
Quizás necesite crear un stub para pasar como argumento constructor. Entonces puedes romper esa cadena de objetos falsos.