web-dev-qa-db-fra.com

PHPUnit: comment mocker plusieurs appels de méthode avec plusieurs arguments?

J'écris un test unitaire pour une méthode utilisant PHPUnit. La méthode que je teste appelle 3 fois la même méthode sur le même objet mais avec des ensembles d'arguments différents. Ma question est similaire aux questions posées ici et ici

Les questions posées dans les autres articles concernent les méthodes de moquerie qui ne prennent qu'un seul argument.

Cependant, ma méthode prend plusieurs arguments et j'ai besoin de quelque chose comme ceci:

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

Ce code ne fonctionne pas car equalTo() ne valide qu'un seul argument. Lui donner plus d'un argument lève une exception:

L'argument n ° 2 de PHPUnit_Framework_Constraint_IsEqual :: __ construct () doit être numérique

Existe-t-il un moyen de se moquer de logicalOr pour une méthode avec plus d'un argument?

Merci d'avance.

46
Thomas

Dans mon cas, la réponse s'est avérée assez 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 clé est d'utiliser $this->at(n), avec n étant le Nième appel de la méthode. Je n'ai rien pu faire avec aucune des variantes de logicalOr() que j'ai essayées.

73

Pour ceux qui cherchent à la fois à faire correspondre les paramètres d'entrée et à fournir des valeurs de retour pour plusieurs appels .. cela fonctionne pour moi:

    $mock->method('myMockedMethod')
         ->withConsecutive([$argA1, $argA2], [$argB1, $argB2], [$argC1, $argC2])
         ->willReturnOnConsecutiveCalls($retValue1, $retValue2, $retValue3);
29
Cody A. Ray

Stubbing un appel de méthode pour renvoyer la valeur d'une carte

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

Ou vous pouvez utiliser

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

si vous n'avez pas besoin de spécifier d'arguments d'entrée

24
scriptin

Si quelqu'un le trouve sans regarder la section correspondante dans la documentation de phpunit, vous pouvez utiliser la méthode withConsecutive

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

Le seul inconvénient est que le code DOIT appeler le MyMockedMethod dans l'ordre des arguments fournis. Je n'ai pas encore trouvé de solution.

10
Pedro A.