PHPUnit: отключить автозагрузчик для проблем с автозагрузкой - PullRequest
1 голос
/ 22 февраля 2012

В моем проекте есть класс, который управляет автозагрузкой.Каждый новый экземпляр класса добавляет свою функцию автозагрузки в стек автозагрузки SPL, а при сбросе экземпляра удаляет свой собственный экземпляр из стека.Класс также экспортирует метод register () и unregister (), который позволяет временно удалить его из стека автозагрузки.

Я пытаюсь написать модульный тест для автозагрузчика и столкнулся с несколькими проблемами.Я включил автозагрузчик в мой скрипт начальной загрузки PHPUnit, чтобы другие тестируемые классы могли загружаться автоматически, как при обычном использовании.Я хочу отключить это поведение на время модульного теста автозагрузчика, поскольку, хотя я могу проводить модульное тестирование, не отключая обычный автозагрузчик, я не мог быть уверен, что мой модульный тест прошел или не прошел из-за экземпляра автозагрузчика, который находится взагрузчик или экземпляр, который я тестирую.

Я попытался сделать следующее в моем файле начальной загрузки:

$unitTestAutoloader = new gordian\reefknot\autoload\Autoload ();

и затем реализовать следующий код в моем модульном тесте:

namespace gordian\reefknot\autoload;

use gordian\exampleclasses;

/**
 * Test class for Autoload.
 * Generated by PHPUnit on 2011-12-17 at 18:10:33.
 */
class AutoloadTest extends \PHPUnit_Framework_TestCase
{
/**
 * @var gordian\reefknot\autoload\Autoload
 */
protected $object;

public function __construct ()
{
    // Disable the unit test autoloader for the duration of the following test
    global $unitTestAutoloader;
    $unitTestAutoloader -> unregister ();
}

public function __destruct ()
{
    // Restore normal autoloading when the test is done
    global $unitTestAutoloader;
    $unitTestAutoloader -> register ();
}

/**
 * Sets up the fixture, for example, opens a network connection.
 * This method is called before a test is executed.
 */
protected function setUp ()
{
    $this -> object = new Autoload ('\\', 'gordian\exampleclasses', __DIR__ . '/exampleclasses');
}

    // Unit tests go here
}

Я думал, что это будет работать, но, к сожалению, он просто выдает ошибку, когда я вместо этого запускаю все модульные тесты, очевидно, потому что автозагрузчик не работает ни для одного из других модульных тестов.

Я подозреваю, что PHPUnit инициализирует все классы модульных тестов перед запуском всех тестов, а мой класс тестов автозагрузчика не позволяет другим классам тестов автоматически загружать классы, которые они должны тестировать.Это правильно?

Можно ли как-нибудь обойти эту проблему?Смогу ли я отключить автозагрузчик по умолчанию каким-либо другим способом, кроме как сделать это в конструкторе тестов?Любые советы в этом случае будут оценены.

Ответы [ 3 ]

1 голос
/ 23 февраля 2012

Причина, по которой автозагрузчик не работает для других тестов, заключается в том, что PHPUnit создает все экземпляры тестовых примеров (по одному на метод тестирования и метод поставщика данных) перед запуском любых тестов и сохраняет их навсегда. Ваш деструктор запускается только после того, как все тесты были выполнены. Как вы обнаружили, вы должны переместить их в setUp() и tearDown(). Я предположил, что это было, когда я прочитал ваш ответ изначально. :)

Кроме того, конструктор тестового примера PHPUnit принимает параметры, которые должны быть переданы вашим переопределенным конструктором - по крайней мере, аргумент $name.

0 голосов
/ 22 февраля 2012

В конце концов я решил переместить код, чтобы отключить обычный автозагрузчик в setup (), и код, чтобы включить его в teartown (). Полный набор тестов теперь работает нормально.

0 голосов
/ 22 февраля 2012

Для своих автозагрузочных модульных тестов я создал несколько классов только для этих тестов, которые находятся в дереве исходников тестов. Так как тестовый каталог не зарегистрирован с реальной автозагрузкой, он не может найти их.

Если вы хотите сделать ваши тесты пуленепробиваемыми, убедитесь, что класс не может быть загружен нормально, используя class_exists().

function testAutoloadLoadsClass() {
    self::assertFalse(class_exists('My_Test_Class'), 'Class should not load normally');
    self::assertTrue($this->fixture->autoload('My_Test_Class'), 'Class should load');
    self::assertTrue(class_exists('My_Test_Class'), 'Class should be loaded now');
}

Первая строка вызовет обычный автозагрузчик, и он не сможет загрузить ваш тестовый класс. Во второй строке используется тестируемый автозагрузчик. Третья строка проверяет, что она действительно была загружена.

...