Comment obtenir que PHPUnit MockObjects renvoie différentes valeurs en fonction d'un paramètre?

StackOverflow https://stackoverflow.com/questions/277914

Question

J'ai un objet fictif PHPUnit qui renvoie 'valeur de retour' , quels que soient ses arguments:

// From inside a test...
$mock = $this->getMock('myObject', 'methodToMock');
$mock->expects($this->any))
     ->method('methodToMock')
     ->will($this->returnValue('return value'));

Ce que je veux pouvoir faire, c'est renvoyer une valeur différente en fonction des arguments passés à la méthode fictive. J'ai essayé quelque chose comme:

$mock = $this->getMock('myObject', 'methodToMock');

// methodToMock('one')
$mock->expects($this->any))
     ->method('methodToMock')
     ->with($this->equalTo('one'))
     ->will($this->returnValue('method called with argument "one"'));

// methodToMock('two')
$mock->expects($this->any))
     ->method('methodToMock')
     ->with($this->equalTo('two'))
     ->will($this->returnValue('method called with argument "two"'));

Mais cela provoque PHPUnit à se plaindre si la maquette n'est pas appelée avec l'argument 'deux' , donc je suppose que la définition de methodToMock ('deux') écrase la définition du premier.

Ma question est donc la suivante: existe-t-il un moyen de faire en sorte qu'un objet fictif PHPUnit renvoie une valeur différente en fonction de ses arguments? Et si oui, comment?

Était-ce utile?

La solution

Utilisez un rappel. par exemple. (directement de la documentation PHPUnit):

<?php
class StubTest extends PHPUnit_Framework_TestCase
{
    public function testReturnCallbackStub()
    {
        $stub = $this->getMock(
          'SomeClass', array('doSomething')
        );

        $stub->expects($this->any())
             ->method('doSomething')
             ->will($this->returnCallback('callback'));

        // $stub->doSomething() returns callback(...)
    }
}

function callback() {
    $args = func_get_args();
    // ...
}
?>

Faites le traitement que vous souhaitez dans le rappel () et renvoyez le résultat en fonction de vos $ args selon le cas.

Autres conseils

De la dernière documentation phpUnit: "Parfois, une méthode stubbed doit renvoyer des valeurs différentes selon une liste d'arguments prédéfinie. Vous pouvez utiliser returnValueMap () pour créer une mappe associant des arguments aux valeurs de retour correspondantes. "

$mock->expects($this->any())
    ->method('getConfigValue')
    ->will(
        $this->returnValueMap(
            array(
                array('firstparam', 'secondparam', 'retval'),
                array('modes', 'foo', array('Array', 'of', 'modes'))
            )
        )
    );

J'avais un problème similaire (bien que légèrement différent ... Je n'avais pas besoin d'une valeur de retour différente basée sur des arguments, mais je devais tester pour nous assurer que 2 jeux d'arguments étaient passés à la même fonction). Je suis tombé sur quelque chose comme ça:

$mock = $this->getMock();
$mock->expects($this->at(0))
    ->method('foo')
    ->with(...)
    ->will($this->returnValue(...));

$mock->expects($this->at(1))
    ->method('foo')
    ->with(...)
    ->will($this->returnValue(...));

Ce n'est pas parfait, car cela nécessite de connaître l'ordre des 2 appels à foo (), mais en pratique, cela n'est probablement pas trop .

Vous voudrez probablement faire un rappel de manière OOP:

<?php
class StubTest extends PHPUnit_Framework_TestCase
{
    public function testReturnAction()
    {
        $object = $this->getMock('class_name', array('method_to_mock'));
        $object->expects($this->any())
            ->method('method_to_mock')
            ->will($this->returnCallback(array($this, 'returnCallback'));

        $object->returnAction('param1');
        // assert what param1 should return here

        $object->returnAction('param2');
        // assert what param2 should return here
    }

    public function returnCallback()
    {
        $args = func_get_args();

        // process $args[0] here and return the data you want to mock
        return 'The parameter was ' . $args[0];
    }
}
?>

Ce n'est pas exactement ce que vous demandez, mais dans certains cas, cela peut aider:

$mock->expects( $this->any() ) )
 ->method( 'methodToMock' )
 ->will( $this->onConsecutiveCalls( 'one', 'two' ) );

onConsecutiveCalls - renvoie une liste de valeurs dans l'ordre spécifié

Passez un tableau à deux niveaux, où chaque élément est un tableau de:

  • sont en premier lieu les paramètres de la méthode et le moins est la valeur renvoyée.

exemple:

->willReturnMap([
    ['firstArg', 'secondArg', 'returnValue']
])

Vous pouvez également renvoyer l'argument comme suit:

$stub = $this->getMock(
  'SomeClass', array('doSomething')
);

$stub->expects($this->any())
     ->method('doSomething')
     ->will($this->returnArgument(0));

Comme vous pouvez le voir dans la documentation fictive , la méthode returnValue ($ index) permet de renvoyer l'argument donné.

Voulez-vous dire quelque chose comme ça?

public function TestSomeCondition($condition){
  $mockObj = $this->getMockObject();
  $mockObj->setReturnValue('yourMethod',$condition);
}

J'ai eu un problème similaire que je ne pouvais pas résoudre (il y a étonnamment peu d'informations sur PHPUnit). Dans mon cas, je viens de faire chaque test test séparé - entrée connue et sortie connue. J'ai réalisé que je n'avais pas besoin de créer un objet fictif touche-à-tout; je n'avais besoin que d'un objet spécifique pour un test spécifique. Ainsi, j'ai séparé les tests et je peux tester des aspects individuels de mon code séparément. unité. Je ne sais pas si cela pourrait vous concerner ou non, mais c'est ce que vous devez tester.

$this->BusinessMock = $this->createMock('AppBundle\Entity\Business');

    public function testBusiness()
    {
        /*
            onConcecutiveCalls : Whether you want that the Stub returns differents values when it will be called .
        */
        $this->BusinessMock ->method('getEmployees')
                                ->will($this->onConsecutiveCalls(
                                            $this->returnArgument(0),
                                            $this->returnValue('employee')                                      
                                            )
                                      );
        // first call

        $this->assertInstanceOf( //$this->returnArgument(0),
                'argument',
                $this->BusinessMock->getEmployees()
                );
       // second call


        $this->assertEquals('employee',$this->BusinessMock->getEmployees()) 
      //$this->returnValue('employee'),


    }

Essayez:

->with($this->equalTo('one'),$this->equalTo('two))->will($this->returnValue('return value'));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top