我正在尝试使用PHPUnit的returnValueMap()来删除读取的结果。它没有产生预期的结果,但是等效的returnCallback()确实如此。如果您想亲自检查一下,我已经提供test case。
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');
结果:
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');
结果:
Subscription ID: NULL
Name: string(12) "Monday Farms"
企业::订阅
public function subscribe() {
echo 'Subscription ID: ';
var_dump($this->field('subscription_id'));
echo 'Name: ';
var_dump($this->field('name'));
}
为什么returnValueMap()不像我期望的那样工作?究竟我错过了什么?
答案 0 :(得分:98)
我遇到了同样的问题,最终发现returnValueMap()必须映射函数的所有参数,包括可选的参数,然后是所需的返回值。
Zend Framework的示例函数:
public function getParam($key, $default = null)
{
$key = (string) $key;
if (isset($this->_params[$key])) {
return $this->_params[$key];
}
return $default;
}
必须像这样映射:
$request->expects($this->any())
->method('getParam')
->will($this->returnValueMap(array(array($param, null, $value))));
如果中间没有null,它将无效。
答案 1 :(得分:8)
我一直在寻找同样的问题并最终走出绝望xdebug - 逐步通过Framework / MockObject / Stub / ReturnValueMap.php和Framework / MockObject / InvocationMocker.php [在方法InvocationMocker :: invoke(PHPUnit_Framework_MockObject_Invocation $)我已经观察了以下几点:
当调用存根函数时,您提供的map数组中的值不仅必须与预期参数相同,而且它们必须具有相同的类型。这是因为在ReturnValueMap :: invoke()方法中的Framework / MockObject / Stub / ReturnValueMap.php中,提供的参数和预期参数之间的比较在第75行中进行了比较,如下所示:
if ($invocation->parameters === $map) {
所以,
的预期结果$mock->myStubbedMethod( "1", "2" )
使用
的地图数组array(
array( 1, 1, 500 ),
array( 1, 2, 700 )
)
会让你失望。相反,结果将为NULL。
在更微妙的一点上,你可能已经使用两种不同的模拟场景来破坏方法(就像我做的那样 - 是的,愚蠢的我!)
因此,为了阐明,第一个模拟存根可以包含
$mock->expects( $this->any() )
->method('myStubbedMethod')
->will( $this->returnValue(750) );
然后,在相同的单元测试方法中,它可以包含
$arrMap = array(
array( 1, 1, 500 ),
array( 1, 2, 700 ),
array( 2, 3, 1500 ),
);
$mock->expects( $this->any() )
->method('myStubbedMethod')
->will( $this->returnValueMap($arrMap) );
调用stubbed方法时,将实现map-array版本。这是显而易见且不言而喻的,但是当你在当下的热度下进行编码,并且在你开发的过程中将不同的代码行为分开时,它很容易被忽视。
答案 2 :(得分:0)
问题似乎存在于代码中的其他位置,或者可能是旧的PHPUnit版本的问题。
对我而言,它使用此代码:
cat 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'));
}
}
<强>输出:强>
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)
所以虽然我不知道为什么它不起作用我至少可以告诉你,你做得对,并且你已经正确理解returnValueMap
:)