2008-11-10 145 views
107

我有一個PHPUnit的mock對象返回'return value'不管它的參數:如何讓PHPUnit MockObjects根據參數返回不同的值?

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

我希望能夠做的是返回基於傳入模擬方法的參數不同的值。我已經試過類似:

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

但是,這會導致PHPUnit來抱怨,如果模擬不與參數'two'叫,所以我假設的methodToMock('two')定義覆蓋了第一個定義。

所以我的問題是:有什麼辦法讓PHPUnit模擬對象根據其參數返回不同的值?如果是這樣,怎麼樣?

回答

99

使用回調。例如(直接從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(); 
    // ... 
} 
?> 

你在回調(想要的任何處理),並返回根據您的$ args適當的結果。

+1

您能否提供文檔鏈接?我似乎無法找到與「谷歌」 – 2010-03-10 18:43:03

+1

http://www.phpunit.de/manual/3.6/en/test-doubles.html#test-doubles.stubs – Steve 2011-01-20 22:08:08

+5

請注意,您可以使用一種方法作爲通過傳遞數組的回調,例如`$這 - > returnCallback(陣列( 'MyClassTest', 'myCallBack函數'))`。 – 2011-07-12 20:30:38

0

你的意思是這樣嗎?

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

我認爲這是SimpleTest的代碼,而不是PHPUnit的。但不,這不是我想要實現的。 說我有一個模擬對象,返回給定數字的單詞。我的模擬方法需要返回「1」時調用1,「2」時調用2等。 $ – 2008-11-10 14:42:06

0

我有一個類似的問題,我不能工作出來(有關PHPUnit的信息令人驚訝的很少)。就我而言,我只是將每個測試分別進行測試 - 已知輸入和已知輸出。我意識到,我不需要製作一個萬能的模擬對象,我只需要一個特定的測試對象,因此我將測試分離出來,並可以單獨測試我的代碼的各個方面單元。我不確定這是否適用於您,但這取決於您需要測試的內容。

+0

不幸的是,這不適用於我的情況。模擬被傳遞到我正在測試的方法中,並且測試方法使用不同的參數調用模擬方法。 知道你不能解決問題很有意思。聽起來這可能是一個PHPUnit限制。 – 2008-11-10 16:01:48

-2

嘗試:

->with($this->equalTo('one'),$this->equalTo('two))->will($this->returnValue('return value')); 
42

我有一個類似的問題(儘管略有不同......我並不需要根據不同的參數的返回值,但必須進行測試,以確保正在通過2臺的參數到相同的功能)。我偶然發現了使用這樣的事情:

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

它並不完美,因爲它要求2的順序調用到foo()是已知的,但在實踐中,這可能不是太

26

你可能會想要做一個回調的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]; 
    } 
} 
?> 
82

從最新的PHPUnit的文檔:「有時候一個存根方法應該返回依據的參數預設列表不同的值可以使用。 returnValueMap()創建一個將參數與相應的返回值關聯的映射。「

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

您也可以返回參數如下:

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

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

正如你可以在Mocking documentation看到,該方法returnValue($index)允許返回給定的參數。

9

這不是你問什麼,但在某些情況下,它可以幫助:

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

onConsecutiveCalls - 按照指定的順序返回值的列表

1

通二級陣列,其中每個元素是一組數組:

  • 首先是方法參數,最少是返回值。

例如:

->willReturnMap([ 
    ['firstArg', 'secondArg', 'returnValue'] 
]) 
-1
$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'), 


    } 
相關問題