Издевательство над объектом PDO с помощью PHPUnit
Мне трудно издеваться над объектом PDO с помощью PHPUnit.
Похоже, в Интернете не так много информации о моей проблеме, но из того, что я могу собрать:
- PDO имеет "окончательные" методы __пробуждения и __сна, которые предотвращают его сериализацию.
- Реализация фиктивного объекта PHPUnit сериализует объект в какой-то момент.
- Модульные тесты затем завершаются ошибкой PHP, сгенерированной PDO, когда это происходит.
Имеется в виду функция чтобы предотвратить такое поведение, добавьте следующую строку в модульный тест:
class MyTest extends PHPUnit_Framework_TestCase
{
protected $backupGlobals = FALSE;
// ...
}
Источник: http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
Это не работает для меня, мой тест все еще выдает ошибку.
Полный тестовый код:
class MyTest extends PHPUnit_Framework_TestCase
{
/**
* @var MyTest
*/
private $MyTestr;
protected $backupGlobals = FALSE;
/**
* Prepares the environment before running a test.
*/
protected function setUp()
{
parent::setUp();
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown()
{
parent::tearDown();
}
public function __construct()
{
$this->backupGlobals = false;
parent::__construct();
}
/**
* Tests MyTest->__construct()
*/
public function test__construct()
{
$pdoMock = $this->getMock('PDO', array('prepare'), array(), '', false);
$classToTest = new MyTest($pdoMock);
// Assert stuff here!
}
// More test code.......
Кто-нибудь из профессионалов PHPUnit поможет мне?
Спасибо,
Бен
3 answers
$BACKUPGLOBALS вам не поможет, потому что эта ошибка исходит из другого источника. PHPUnit 3.5.2 (возможно, и более ранние версии) содержит следующий код в PHPUnit/Framework/MockObject/Generator.php
if ($callOriginalConstructor &&
!interface_exists($originalClassName, $callAutoload)) {
if (count($arguments) == 0) {
$mockObject = new $mock['mockClassName'];
} else {
$mockClass = new ReflectionClass($mock['mockClassName']);
$mockObject = $mockClass->newInstanceArgs($arguments);
}
} else {
// Use a trick to create a new object of a class
// without invoking its constructor.
$mockObject = unserialize(
sprintf(
'O:%d:"%s":0:{}',
strlen($mock['mockClassName']), $mock['mockClassName']
)
);
}
Этот "трюк" с несериализацией используется, когда вы просите getmock не выполнять исходный конструктор, и он быстро завершится неудачей с PDO.
Итак, как же обойти это?
Одним из вариантов является создание помощника по тестированию, подобного этому
class mockPDO extends PDO
{
public function __construct ()
{}
}
Цель здесь состоит в том, чтобы получить избавьтесь от оригинального конструктора PDO, который вам не нужен. Затем измените свой тестовый код на следующий:
$pdoMock = $this->getMock('mockPDO', array('prepare'));
Создание макета, подобного этому, приведет к выполнению оригинального конструктора, но поскольку теперь он безвреден благодаря помощнику по тестированию mockPDO, вы можете продолжить тестирование.
Лучшее, что я могу придумать, это использовать runkit и переопределить два последних метода как защищенные с помощью runkit_function_redefine.
Не включайте параметр runkit.internal_override в php.ini.
для get, чтобы включить параметр runkit.internal_override в php.ini.И, как всегда, как и в случае с eval, если runkit кажется ответом, вопрос, вероятно, неверен:)
Вы создаете экземпляр своего тестового случая в своем тестовом случае?
$classToTest = new MyTest($pdoMock);
Прямо сейчас вы, по сути, тестируете свой тестовый случай. Это должно быть что-то вроде:
$classToTest = new My($pdoMock);