2012-10-05 22 views
29

Ich versuche, PHPUnit returnValueMap() zu verwenden, um die Ergebnisse eines Lesevorgangs auszugeben. Es liefert nicht die erwarteten Ergebnisse, aber eine äquivalente returnCallback() tut. Ich habe meine test case zur Verfügung gestellt, wenn Sie es selbst überprüfen möchten.PHPUnit returnValueMap liefert keine erwarteten Ergebnisse

returnValueMap()

$enterprise = $this->getMock('Enterprise', array('field')); 
$enterprise->expects($this->any()) 
    ->method('field') 
    ->will($this->returnValueMap(array(
     array('subscription_id', null), 
     array('name', 'Monday Farms') 
    ))); 
$enterprise->subscribe('basic'); 

Ergebnisse:

Subscription ID: NULL 
Name: NULL 

returnCallback()

$enterprise = $this->getMock('Enterprise', array('field')); 
$enterprise->expects($this->any()) 
    ->method('field') 
    ->will($this->returnCallback(function ($arg) { 
     $map = array(
      'subscription_id' => null, 
      'name' => 'Monday Farms' 
     ); 
     return $map[$arg]; 
    })); 
$enterprise->subscribe('basic'); 

Ergebnisse:

Subscription ID: NULL 
Name: string(12) "Monday Farms" 

Unternehmen :: abonnieren

public function subscribe() { 
    echo 'Subscription ID: '; 
    var_dump($this->field('subscription_id')); 
    echo 'Name: '; 
    var_dump($this->field('name')); 
} 

Warum returnValueMap nicht() arbeiten, wie ich es zu erwarten? Was genau vermisse ich?

Antwort

82

Ich hatte das gleiche Problem und fand schließlich heraus, dass returnValueMap() alle Parameter Ihrer Funktion, mit optionalen, dann den gewünschten Rückgabewert zuordnen muss.

Beispiel Funktion von Zend Framework:

public function getParam($key, $default = null) 
{ 
    $key = (string) $key; 
    if (isset($this->_params[$key])) { 
     return $this->_params[$key]; 
    } 

    return $default; 
} 

hat wie diese abgebildet:

$request->expects($this->any()) 
     ->method('getParam') 
     ->will($this->returnValueMap(array(array($param, null, $value)))); 

Ohne die Null in der Mitte, wird es nicht funktionieren.

+0

Sie haben meinen Tag gerettet! Vielen Dank! – haltabush

+9

Sie haben mich gerade gerettet ** eine Menge Kopfschmerzen. Vielen Dank. PS: Schade, dass viele Eigenarten von PHPUnit nicht in der offiziellen Dokumentation enthalten sind .... –

+0

Lebensretter! Es gibt auch Fälle, in denen der Nullwert "falsch" sein muss, insbesondere wenn "$ param" (der Schlüssel) eine ganze Zahl ist – esh

0

Das Problem scheint entweder irgendwo anders im Code zu liegen oder könnte ein Problem mit einer alten PHPUnit-Version sein.

Bei mir funktioniert es mit diesem Code:

Katze EnterpriseTest.php

<?php 

class EnterpriseTest extends PHPUnit_Framework_TestCase { 

    public function testReturnValueMap() { 
     $enterprise = $this->getMock('Enterprise', array('field')); 
     $enterprise->expects($this->any()) 
      ->method('field') 
      ->will($this->returnValueMap(array(
       array('subscription_id', null), 
       array('name', 'Monday Farms') 
      ))) 
     ; 
     $enterprise->subscribe('basic');   
    } 

} 

class Enterprise { 

    public function field($name) { 
    } 

    public function subscribe() { 
     echo 'Subscription ID: '; 
     var_dump($this->field('subscription_id')); 
     echo 'Name: '; 
     var_dump($this->field('name')); 
    } 

} 

Ausgang:

phpunit-dev EnterpriseTest.php 
PHPUnit 3.7.6 by Sebastian Bergmann. 

.Subscription ID: NULL 
Name: string(12) "Monday Farms" 


Time: 0 seconds, Memory: 6.75Mb 

OK (1 test, 1 assertion) 

So, während ich kann nicht sagen, warum es doesn Ich kann dir wenigstens sagen, dass du es richtig machst und dass du verstanden hast returnValueMap c orrectly :)

8

Ich habe dieses gleiche Problem und schließlich aus der Verzweiflung xdebug-gestaffelt durch Framework/MockObject/Stub/ReturnValueMap.php und Framework/MockObject/InvocationMocker gejagt.php [Methode InvocationMocker :: aufrufen (PHPUnit_Framework_MockObject_Invocation $ Aufruf)], und ich habe die folgenden Punkte zu beachten:

  1. Nicht nur müssen die Werte in der Karte-Array, das Sie die gleiche Versorgung wie die erwartete Parameter, wenn die Stub-Funktion aufgerufen wird, aber sie müssen von der gleichen Art sein. Dies liegt daran, innerhalb Rahmen/MockObject/Stub/ReturnValueMap.php im ReturnValueMap :: aufrufen() -Methode, der Vergleich zwischen den angegebenen Parametern und den erwarteten Parameter verglichen wird in Zeile 75 wie folgt:

    if ($invocation->parameters === $map) { 
    

    So, das erwartete Ergebnis von

    $mock->myStubbedMethod("1", "2") 
    

    Karte-Array von

    array(
        array(1, 1, 500), 
        array(1, 2, 700) 
    ) 
    

    wird enttäuscht werden. Stattdessen wird das Ergebnis ein NULL sein.

  2. Auf einem viel subtiler Punkt, können Sie das Verfahren unter Verwendung von zwei verschiedenen Mock Szenarien stubbed haben (so wie ich - ja, dumm von mir)

    Also, die erste Mock-Stub konnte aufzuklären, enthalten

    $mock->expects($this->any()) 
         ->method('myStubbedMethod') 
         ->will($this->returnValue(750)); 
    

    und später dann in den gleichen Einheit-Testverfahren, könnte es

    $arrMap = array(
        array(1, 1, 500), 
        array(1, 2, 700), 
        array(2, 3, 1500), 
    ); 
    $mock->expects($this->any()) 
         ->method('myStubbedMethod') 
         ->will($this->returnValueMap($arrMap)); 
    

    enthält Wenn die Stub-Methode aufgerufen wird, wird die Karte-Array-Version im sein plementiert. Dies ist offensichtlich und selbstverständlich, aber während Sie in der Hitze des Augenblicks kodieren, und während Sie sich entwickeln, wird das unterschiedliche Code-Verhalten in Ihrem Geist voneinander getrennt.

Verwandte Themen