PHPUnit returnValueMap не дает ожидаемых результатов
Я пытаюсь использовать PHPUnit returnValueMap(), чтобы заглушить результаты чтения. Это не дает ожидаемых результатов, но эквивалент returnCallback(). Я сделал свой тестовый пример доступным, если вы хотите проверить его самостоятельно.
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'));
}
Почему не возвращает функциюValueMap(), как я ожидаю? Что именно мне не хватает?
Ответы
Ответ 1
У меня была такая же проблема, и в итоге выяснилось, что 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))));
Без нуля в середине, это не сработает.
Ответ 2
Я искал эту проблему и в итоге вышел из отчаяния xdebug-stepped через Framework/MockObject/Stub/ReturnValueMap.php и Framework/MockObject/InvocationMocker.php [в методе InvocationMocker:: invoke (PHPUnit_Framework_MockObject_Invocation $invocation) ], и я заметил следующие моменты:
-
Значения в массиве map, которые вы поставляете, должны не совпадать с ожидаемыми параметрами при вызове функции stubbed, но они ДОЛЖНЫ БЫТЬ ОДНОГО ТИПА. Это связано с тем, что внутри Framework/MockObject/Stub/ReturnValueMap.php в методе ReturnValueMap:: invoke() сравнение между параметрами и ожидаемыми параметрами сравнивается в строке 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) );
а затем, в том же методе unit-test, он может содержать
$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-method, будет реализована версия map-array. Это очевидно и само собой разумеется, однако, при кодировании в разгар момента и при раздельном разном кодовом поведении в вашем сознании, когда вы развиваетесь, его легко упускают из виду.
Ответ 3
Проблема, похоже, лежит либо в другом месте кода, либо может быть проблемой со старой версией 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
:)