run readthedocs example descargar curso php phpunit

example - phpunit readthedocs



Modificando objetos en returnCallback() de PHPUnit Mocks (3)

El alex

Hablé con Sebastian (el creador de phpunit) sobre ese problema y sí: el argumento se clone antes de pasar a la devolución de llamada.

Desde lo alto de mi cabeza, no puedo ofrecerte ninguna solución, pero elijo responder de todas formas para al menos decirte que no estás haciendo nada malo y que este es el comportamiento esperado.

Para citar el comentario de Sebastians en IRC sobre por qué se clona el argumento:

Es un debate de larga duración entre mí, yo y los usuarios de PHPUnit si esto es correcto o no ;-)

Para tener algo copiar / pegar:

La afirmación 3 en esta muestra de código fallará. (La variable solo se cambia en el objeto devuelto)

<?php class A { function foobar($o) { $o->x = mt_rand(5, 100); } } class Test extends PHPUnit_Framework_TestCase { public function testFoo() { $mock = $this->getMock(''A''); $mock->expects($this->any()) ->method(''foobar'') ->will($this->returnCallback(function($o) { $o->x = 2; return $o; })); $o = new StdClass; $o->x = 1; $this->assertEquals(1, $o->x); $return = $mock->foobar($o); $this->assertEquals(2, $return->x); $this->assertEquals(2, $o->x); } }

Actualizar:

A partir de PHPUnit 3.7 se puede desactivar la clonación. Mira el último argumento apagado:

public function getMock( $originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '''', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE );

Incluso podría estar apagado por defecto :)

Quiero simular un método de una clase y ejecutar una devolución de llamada que modifica el objeto dado como parámetro (utilizando PHP 5.3 con PHPUnit 3.5.5)

Digamos que tengo la siguiente clase:

class A { function foobar($object) { doSomething(); } }

Y este código de configuración:

$mock = $this->getMockBuilder(''A'')->getMock(); $mock->expects($this->any())->method(''foobar'')->will( $this->returnCallback(function($object) { $object->property = something; }));

Por alguna razón el objeto no se modifica. En var_dump ing $object veo que es el objeto correcto. ¿Podría ser que el objeto se pasa por valor? ¿Cómo puedo configurar el simulacro para recibir una referencia?


Esto es realmente viejo, pero apareció en la parte superior de una búsqueda y me indicó la dirección correcta, así que vale la pena actualizarlo. Desde PHPUnit 6.0, use disableArgumentCloning() , así:

return $this->getMockBuilder(''A'') ->disableOriginalConstructor() ->disableArgumentCloning() ->setMethods(array(''foobar'')) ->getMock() ;


La clase que realiza la clonación de los parámetros pasados ​​al método PHPUnit_Framework_MockObject_Invocation_Static es PHPUnit_Framework_MockObject_Invocation_Static . Si cloneObject() , verá que devolverá el objeto original si el método __clone() la clase del __clone() no es público.

Si tiene control sobre la clase de los objetos de parámetros y no necesita clonarlos nunca, puede agregar un método privado vacío __clone() .