我有一个PHPUnit模拟对象,'return value'
无论它的参数是什么都返回:
// From inside a test... $mock = $this->getMock('myObject', 'methodToMock'); $mock->expects($this->any)) ->method('methodToMock') ->will($this->returnValue('return value'));
我想要做的是根据传递给mock方法的参数返回一个不同的值.我尝试过类似的东西:
$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"'));
但是如果没有使用参数调用mock,这会导致PHPUnit抱怨'two'
,所以我假设定义methodToMock('two')
覆盖了第一个的定义.
所以我的问题是:有没有办法让PHPUnit模拟对象根据其参数返回不同的值?如果是这样,怎么样?
使用回调.例如(直接来自PHPUnit文档):
getMock( 'SomeClass', array('doSomething') ); $stub->expects($this->any()) ->method('doSomething') ->will($this->returnCallback('callback')); // $stub->doSomething() returns callback(...) } } function callback() { $args = func_get_args(); // ... } ?>
在callback()中执行您想要的任何处理,并根据您的$ args返回结果.
从最新的phpUnit文档:"有时,存根方法应根据预定义的参数列表返回不同的值.您可以使用returnValueMap()创建一个将参数与相应的返回值相关联的映射."
$mock->expects($this->any()) ->method('getConfigValue') ->will( $this->returnValueMap( array( array('firstparam', 'secondparam', 'retval'), array('modes', 'foo', array('Array', 'of', 'modes')) ) ) );
我有一个类似的问题(虽然略有不同......我不需要基于参数的不同返回值,但必须测试以确保将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(...));
它并不完美,因为它需要知道对foo()的2次调用的顺序,但实际上这可能并不太糟糕.
您可能希望以OOP方式进行回调:
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]; } } ?>
这不是你要求的,但在某些情况下它可以帮助:
$mock->expects( $this->any() ) ) ->method( 'methodToMock' ) ->will( $this->onConsecutiveCalls( 'one', 'two' ) );
onConsecutiveCalls - 以指定的顺序返回值列表