Pregunta phpunit evitar los argumentos del constructor para simular


¿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 establecer 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í.


76
2017-11-10 23:00


origen


Respuestas:


Puedes usar getMockBuilder en lugar de simplemente getMock:

$mock = $this->getMockBuilder('class_name')
    ->disableOriginalConstructor()
    ->getMock();

Ver la sección sobre "Prueba Dobles" en Documentación de PHPUnit para 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.


125
2018-06-08 10:11



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);

40
2018-03-09 22:38



Como una adición, quería adjuntar expects() llama a mi objeto burlado y luego llama al constructor. En PHPUnit 3.7.14, el objeto que se devuelve cuando llama 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);

Nota, si functionCallFromConstruct es protected, específicamente debes usar setMethods() para que el método protegido sea burlado. Ejemplo:

    $mock->setMethods(array('functionCallFromConstructor'));

setMethods() debe llamarse antes del expect() llamada. Personalmente, encadenó esto después disableOriginalConstructor() pero antes getMock().


3
2018-03-08 02:21



Quizás necesite crear un stub para pasar como argumento constructor. Entonces puedes romper esa cadena de objetos falsos.


1
2017-12-01 22:30



Alternativamente, puede 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.


1
2017-07-21 07:37



PHPUnit está diseñado para llamar al constructor en objetos burlados; Para evitar esto, debe hacer lo siguiente:

  1. Inyecta un objeto simulado como una dependencia en el objeto con el que estás teniendo problemas para burlarte
  2. Cree una clase de prueba que amplíe la clase a la que intenta llamar y que no llame al constructor padre

0
2017-12-08 21:08