2012-06-08 24 views
38

Estoy escribiendo una prueba unitaria para un método que utiliza PHPUnit. El método que estoy probando hace una llamada al mismo método en el mismo objeto 3 veces pero con diferentes conjuntos de argumentos. Mi pregunta es similar a las preguntas here y herePHPUnit: ¿cómo me burlo de múltiples llamadas a métodos con múltiples argumentos?

Las preguntas formuladas en las otras publicaciones tienen que ver con los métodos de burla que solo tienen un argumento.

Sin embargo, mi método tiene varios argumentos y necesito algo como esto:

$mock->expects($this->exactly(3)) 
    ->method('MyMockedMethod') 
    ->with($this->logicalOr($this->equalTo($arg1, $arg2, arg3....argNb), 
          $this->equalTo($arg1b, $arg2b, arg3b....argNb), 
          $this->equalTo($arg1c, $arg2c, arg3c....argNc) 
     )) 

Este código no funciona porque equalTo() valida sólo un argumento. Dándole más de un argumento se emite una excepción:

Argumento # 2 de PHPUnit_Framework_Constraint_IsEqual :: __ construct() debe ser un valor numérico

¿Hay una manera de hacer un logicalOr burlarse de un método con más de un argumento?

Gracias de antemano.

+0

No ha formulado una pregunta (con palabras reales). Además, no ha explicado por qué el código que agregó específicamente no funciona para usted. Eso puede sonar redundante, pero esa información ayudará a que su pregunta sea más clara y más fácil de dar una respuesta. No podemos mirar dentro de tu cerebro. – hakre

+0

@Thomas: Vine aquí para hacer esta pregunta * exacta *, así que actualicé y voté como tuya, espero que no te importe. (Y ahora jugamos el juego de espera ...) –

+0

@drHannibalLecter gracias – Thomas

Respuesta

53

En mi caso la respuesta resultó ser bastante simple:

$this->expects($this->at(0)) 
    ->method('write') 
    ->with(/* first set of params */); 

$this->expects($this->at(1)) 
    ->method('write') 
    ->with(/* second set of params */); 

La clave es usar $this->at(n), con n siendo la enésima llamada del método. No pude hacer nada con ninguna de las variantes logicalOr() que probé.

+0

Creo que la clave aquí es que 'with' toma una serie de restricciones (lo que implica un' equalTo' si solo se da un valor). Usted * debería * poder usar 'logicalOr', pero solo en el contexto de cada argumento por separado (lo que podría no ser muy útil). –

+0

@JohnFlatness: ¡Tienes razón, yo * debería *! :) Estoy sorprendido por el hecho de que algo tan básico se limita a un argumento. –

+2

@drHannibalLecter Esto funciona, pero el problema aquí es que codifica duro su prueba para preocuparse por la implementación interna del caso de prueba. – Thomas

17

Stubbing a method call to return the value from a map

$map = array(
    array('arg1_1', 'arg2_1', 'arg3_1', 'return_1'), 
    array('arg1_2', 'arg2_2', 'arg3_2', 'return_2'), 
    array('arg1_3', 'arg2_3', 'arg3_3', 'return_3'), 
); 
$mock->expects($this->exactly(3)) 
    ->method('MyMockedMethod') 
    ->will($this->returnValueMap($map)); 

O puede utilizar

$mock->expects($this->exactly(3)) 
    ->method('MyMockedMethod') 
    ->will($this->onConsecutiveCalls('return_1', 'return_2', 'return_3')); 

si no es necesario especificar los argumentos de entrada

+0

Ha entendido mal la pregunta, no se trata de los valores de devolución, se trata de diferentes argumentos para múltiples llamadas del método. –

+1

@drHannibalLecter OK, lo tengo. Simplemente confundir 'with()'/'will()' – scriptin

+0

en llamadas consecutivas es mucho mejor que hacerlo manualmente en() – Blacksonic

7

En caso de que alguien encuentra esto sin mirar el correspondent section en la documentación de PHPUnit, puede utilizar el método withConsecutive

$mock->expects($this->exactly(3)) 
    ->method('MyMockedMethod') 
    ->withConsecutive(
     [$arg1, $arg2, $arg3....$argNb], 
     [arg1b, $arg2b, $arg3b....$argNb], 
     [$arg1c, $arg2c, $arg3c....$argNc] 
     ... 
    ); 

La única desventaja de esto es que el código debe llamar a la MyMockedMethod en el orden de los argumentos suministrados Todavía no he encontrado una forma de evitar esto.

+1

Creo que esto es lo que las funciones de "mapa" son para, por ejemplo, willReturnMap o returnValueMap - como una búsqueda de params a devoluciones. – scipilot

12

Para otros que están buscando a los dos parámetros de entrada de partido y proporcionan valores de retorno para múltiples llamadas .. Esto funciona para mí:

$mock->method('myMockedMethod') 
     ->withConsecutive([$argA1, $argA2], [$argB1, $argB2], [$argC1, $argC2]) 
     ->willReturnOnConsecutiveCalls($retValue1, $retValue2, $retValue3); 
Cuestiones relacionadas