Я строю класс управления сеансом и связанный с ним модульный тест. Чтобы отделить класс от глобального состояния $ _SESSION, я использую чрезвычайно простой класс для управления связью между классом и данными сеанса.PHPUnit Mock, который возвращает один и тот же массив каждый раз
Весь источник Binding класса выглядит следующим образом:
class Binding implements iface\Binding
{
public function &getNamespace ($namespace)
{
return $_SESSION [$namespace];
}
}
В потребляющего класса Session У меня есть следующие:
protected function initStorage()
{
// Check that storage hasn't already been bound to the session
if ($this -> storage === NULL)
{
// Attempt to start the session if it hasn't already been started
if (($this -> sessionId() !== '')
|| ((!$this -> headersSent())
&& ($this -> startSession())))
{
// Bind the storage to the session
$this -> storage =& $this -> binding -> getNamespace ($this -> namespace);
// Make sure the session is in a usable state
if (!$this -> hasData())
{
$this -> reset();
}
}
else
{
// We couldn't start the session
throw new \RuntimeException (__METHOD__ . ': Unable to initiate session storage at this time');
}
}
return $this;
}
SESSIONID, headersSent и startSession простые функции однолинейные которые служат в качестве «тестовых швов», которые я могу легко заменить на mocks в PHPUnit.
Я понял, что при написании теста я мог бы сделать больше с классом связывания привязки, чем просто отсоединить сеанс от класса, я мог бы также использовать его как способ наблюдения за непубличным свойством класса, фактически выставляют любое внутреннее состояние и тем самым делают класс хрупким. Поскольку класс работает с ссылкой на массив, а не непосредственно на массив, я могу наблюдать привязанный массив.
Я надеялся сделать это с издевательским API PHPUnit, но я не могу понять, как это сделать.
Я знаю, что могу создать макет, который возвращает массив так:
$mock = $this -> getMock ('iface\Binding');
$mock -> expects ($this -> any())
-> method ('getNamespace')
-> will ($this -> returnValue (array()));
Это не полезно для наблюдения изменений состояния, хотя, как он возвращает другой массив каждый раз. Мне нужен макет, который каждый раз возвращает ссылку на один и тот же массив.
В конце концов я написал класс, чтобы занять место реального Binding класса и использовать его вместо:
class BindingMock implements iface\Binding
{
protected $storage = array();
public function &getNamespace ($namespace)
{
return $this -> storage [$namespace];
}
}
Используя этот класс позволяет мне исследовать содержимое $ хранения до и после вызова что-то в Session API, потому что я могу посмотреть, что находится в массиве хранения, не открывая в классе Session непубличное состояние. Вот пример теста, который использует технику:
public function testCreateItem()
{
$storage =& $this -> binding -> getNamespace ('unittest');
$this -> assertEmpty ($storage);
$this -> object -> createItem ('This is a test', 'test');
$this -> assertNotEmpty ($storage);
$this -> assertEquals ('This is a test', $storage ['test']);
}
Я предпочел бы быть в состоянии генерировать класс замены с использованием PHPUnit, хотя, имея дополнительный класс только для модульного тестирования кажется, неправильный путь, чтобы сделать это, если в PHPUnit нет способа добиться того же.
Не в сети ... хороший аватар! – Jrod