2008-11-10 146 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'), 


    } 
相关问题