Подтвердить что ты не робот

Как вы используете PHPUnit для проверки функции, если эта функция должна убивать PHP?

По существу у меня есть метод класса killProgram, который предназначен для отправки перенаправления hTTP, а затем для удаления PHP.

Как я должен проверить это? Когда я запускаю phpunit, он ничего не возвращает для этого теста и полностью закрывается.

Сейчас я рассматриваю возможность использования функции killProgram для исключения, которое не должно обрабатываться, что позволило бы мне утверждать, что было создано исключение.

Есть ли лучший способ?

4b9b3361

Ответ 1

Поскольку каждый тест выполняется одним и тем же процессом PHPUnit, если вы используете exit/die в своем PHP-коде, вы все убьете - как вы заметили ^^

Итак, вы должны найти другое решение, да - как возвращение вместо смерти; или бросать исключение (вы можете проверить, не вызвал ли какой-либо проверенный код ожидаемое исключение).

Может быть, PHPUnit 3.4 и он --process-isolation switch (см. При необходимости выполнить каждый тест с помощью отдельного процесса PHP) может help (не имея все умирающего), но вы все равно не сможете получить результат теста, если PHPUnit не получит контроль.

У меня была эта проблема несколько раз; решает его, возвращаясь, а не умирая - даже возвращаясь несколько раз, если нужно, чтобы вернуться "достаточно высоко" в стек вызовов ^ ^
В конце концов, я полагаю, у меня больше нет "смерти" в моем приложении... Вероятно, лучше, когда думаешь о MVC, кстати.

Ответ 2

Это, очевидно, старый вопрос, но моим предложением было бы переместить код die() в отдельный метод, который вы можете затем высмеять.

В качестве примера вместо этого:

class SomeClass
{
    public function do()
    {
        exit(1);
        // or
        die('Message');
    }
}

сделайте следующее:

class SomeClass
{
    public function do()
    {
        $this->terminate(123);
        // or
        $this->terminate('Message');
    }

    protected function terminate($code = 0)
    {
        exit($code);
    }

    // or 
    protected function terminate($message = '')
    {
        die($message);
    }
}

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

Ваш тест будет выглядеть примерно так:

class SomeClassTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @expectedExceptionCode 123
     */
    public function testDoFail()
    {
        $mock = $this->getMock('SomeClass');
        $mock->expects($this->any())
             ->method('terminate')
             ->will($this->returnCallback(function($code) {
                 throw new \Exception($code);
             }));

        // run to fail
        $mock->do();
    }
}

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

Ответ 3

Нет необходимости изменять код, чтобы проверить его, вы можете просто использовать set_exit_overload() (предоставленный test_helpers от того же автора, что и PHPUnit).

Ответ 4

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

Вместо использования die() вы можете использовать throw new RuntimeException() (или собственный класс исключений), который также остановит выполнение программы (хотя и по-другому) и использует PHPUnit setExpectedException(), чтобы поймать его. Если вы хотите, чтобы ваш script до die(), когда это исключение встречается, абсолютно ничего не печатать на уровне пользователя, посмотрите set_exception_handler().

В частности, я думаю о сценарии, в котором вы помещаете set_exception_handler() -call в файл начальной загрузки, который тесты не используют, поэтому обработчик не будет запускать его независимо от сценария, поэтому ничего вмешивается в работу с обработкой исключительных ошибок PHPUnit.

Ответ 5

Это относится к набору проблем, с которыми я получаю некоторый старый код для прохождения теста. Поэтому я придумал класс Testable, подобный этому...

class Testable {
   static function exitphp() {
      if (defined('UNIT_TESTING')) {
         throw new TestingPhpExitException();
      } else {
         exit();
      }
   }
}

Теперь я просто заменяю вызовы на exit() с помощью Testable:: exitphp().

Если он тестируется, я просто определяю UNIT_TESTING, в производстве я этого не делаю. Похоже на простой макет.

Ответ 6

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

Таким образом, вы убиваете на производстве или создаете исключение в тестовой среде.

Любой призыв умереть или выйти, убивает весь процесс...

Это должен был быть комментарий, но я не могу комментировать уровень моих очков репутации.