Wie kann ich PHPUnit MockObjects unterschiedliche Werte zurückgeben basierend auf einem Parameter?

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

Frage

Ich habe ein PHPUnit Mock-Objekt bekam die 'return value' egal, was seine Argumente zurückgibt:

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

Was ich tun möchte in der Lage sein, einen anderen Wert zurück, basierend auf übergeben die Argumente an die Mock-Methode. Ich habe versucht, so etwas wie:

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

Aber dies führt PHPUnit zu beschweren, wenn das Mock nicht mit dem Argument 'two' genannt wird, so nehme ich an, dass die Definition von methodToMock('two') die Definition des ersten überschreibt.

Also meine Frage ist: Gibt es eine Möglichkeit, ein PHPUnit Mock-Objekt zu erhalten, einen anderen Wert auf seinen Argumente basieren zurückzukehren? Und wenn ja, wie?

War es hilfreich?

Lösung

einen Rückruf verwenden. z.B. (Gerade von PHPUnit Dokumentation):

<?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();
    // ...
}
?>

Tu, was die Verarbeitung Sie in dem Rückruf wollen () und gab das Ergebnis auf der Grundlage Ihres $ args als angemessen.

Andere Tipps

Von dem neuesten PHPUnit docs: „Manchmal sollte eine Stub-Methode unterschiedliche Werte zurückgeben, je nach einer vordefinierten Liste von Argumenten Sie verwenden können, returnValueMap () eine Karte zu erstellen, die Argumente mit entsprechenden Rückgabewerte zuordnet."

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

Ich hatte ein ähnliches Problem (wenn auch etwas anders ... Ich habe nicht auf Argumente benötigt unterschiedlichen Rückgabewert basierte, hatte aber zu testen 2 Sätze Argumente, um sicherzustellen, wurden auf die gleiche Funktion übergeben werden). Ich stolperte so etwas wie dies bei der Verwendung:

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

Es ist nicht perfekt, da es die Reihenfolge der zwei Anrufe zu foo () bekannt erfordert das, aber in der Praxis ist dies wahrscheinlich nicht zu schlecht.

Sie würden wahrscheinlich wollen einen Rückruf in einer OOP Art und Weise zu tun:

<?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];
    }
}
?>

Es ist nicht genau das, was Sie fragen, aber in manchen Fällen kann es helfen:

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

onConsecutiveCalls - gibt eine Liste von Werten in der angegebenen Reihenfolge

Geben zwei Level-Array, wobei jedes Element ist eine Anordnung von:

  • sind erste Verfahrensparameter, und dest Rückgabewert.

Beispiel:

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

Sie können auch das Argument zurück, wie folgt:

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

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

Wie können Sie in der Mocking Dokumentation , wobei das Verfahren returnValue($index) ermöglicht das gegebene Argument zurück.

Meinst du so etwas?

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

Ich hatte ein ähnliches Problem, das ich nicht so gut funktionieren könnte (es gibt überraschend wenig Informationen über für PHPUnit). In meinem Fall habe ich nur jeden Test separaten Test - bekannt Eingang und Ausgang bekannt. Ich erkennen, dass ich nicht ein Jack-of-all-trades Mock-Objekt vornehmen müssen, ich brauchte nur einen spezifischen für einen bestimmten Test, und so trennte ich die Tests und einzelne Aspekte meines Codes als separates testen Einheit. Ich bin mir nicht sicher, ob dies für Sie anwendbar sein könnte oder nicht, aber das ist auf, was Sie testen müssen.

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


    }

Versuchen:

->with($this->equalTo('one'),$this->equalTo('two))->will($this->returnValue('return value'));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top