Как проверить контроллеры с помощью CodeIgniter? - PullRequest
12 голосов
/ 16 июля 2009

У меня есть веб-приложение на PHP, созданное на основе CodeIgniter MVC. Я хочу протестировать различные классы контроллеров. Я использую Toast для модульного тестирования. У моих контроллеров нет состояния, все, что они обрабатывают, либо сохраняется в сеансе, либо передается для просмотра. Создать фиктивный объект сеанса и проверить, правильно ли он работает, просто (просто создайте фиктивный объект и введите его с помощью $ controller-> session = $ mock).

Чего я не знаю, так это как работать с представлениями. В CodeIgniter представления загружаются как:

$this->load->view($view_name, $vars, $return);

Поскольку я не хочу изменять код CI, я мог бы создать фиктивный загрузчик и заменить оригинал. И здесь кроется проблема, я не могу найти способ получить новый класс из CI_Loader.

Если я не включаю файл system / library / Loader.php, класс CI_Loader не определен, и я не могу наследовать от него:

class Loader_mock extends CI_Loader

Если я включаю файл (используя require_once), я получаю ошибку:

Cannot redeclare class CI_Loader

Похоже, что сам код CI не использует require_once по любой причине.

Есть ли у кого-нибудь здесь опыт модульного тестирования приложений на базе CodeIgniter?

Редактировать: Я пытался внедрить настоящий объект загрузчика во время выполнения в фиктивный класс и перенаправить все вызовы и переменные с помощью __call, __set, __get, __isset и __unset. Но, похоже, это не работает (хотя я не получаю никаких ошибок, просто нет вывода, то есть пустой страницы из Toast). Вот код:

class Loader_mock 
{
    public $real_loader;
    public $varijable = array();

    public function Loader_mock($real)
    {
        $this->real_loader = $real;
    }

    public function __call($name, $arguments) 
    {
        return $this->real_loader->$name($arguments);
    }

    public function __set($name, $value)
    {
        return $this->real_loader->$name = $value;
    }

    public function __isset($name)
    {
        return isset($this->real_loader->$name);
    }

    public function __unset($name)
    {
        unset($this->loader->$name);
    }

    public function __get($name)
    {
        return $this->real_loader->$name;
    }

    public function view($view, $vars = array(), $return = FALSE)
    {
        $varijable = $vars;
    }
}

Ответы [ 5 ]

4 голосов
/ 05 ноября 2009

В качестве альтернативы, вы можете сделать это:

$CI =& get_instance();
$CI = load_class('Loader');

class MockLoader extends CI_Loader
{
    function __construct()
    {
        parent::__construct();
    }
}

Затем в вашем контроллере выполните $ this-> load = new MockLoader ().

2 голосов
/ 17 июля 2009

Мое текущее решение - изменить код CodeIgniter для использования require_once вместо require. Вот патч, который я собираюсь отправить разработчикам CI на тот случай, если кому-то нужно сделать то же самое, пока они его не примут:

diff --git a/system/codeigniter/Common.php b/system/codeigniter/Common.php
--- a/system/codeigniter/Common.php
+++ b/system/codeigniter/Common.php
@@ -100,20 +100,20 @@ function &load_class($class, $instantiate = TRUE)
        // folder we'll load the native class from the system/libraries folder.
        if (file_exists(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT))
        {
-               require(BASEPATH.'libraries/'.$class.EXT);
-               require(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT);
+               require_once(BASEPATH.'libraries/'.$class.EXT);
+               require_once(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT);
                $is_subclass = TRUE;
        }
        else
        {
                if (file_exists(APPPATH.'libraries/'.$class.EXT))
                {
-                       require(APPPATH.'libraries/'.$class.EXT);
+                       require_once(APPPATH.'libraries/'.$class.EXT);
                        $is_subclass = FALSE;
                }
                else
                {
-                       require(BASEPATH.'libraries/'.$class.EXT);
+                       require_once(BASEPATH.'libraries/'.$class.EXT);
                        $is_subclass = FALSE;
                }
        }
1 голос
/ 21 июля 2009

Я впечатлен кодом, который вы пытаетесь использовать.

Так что теперь мне интересно, как класс CodeIgniter 'Hooks' может помочь вашей проблеме?

http://codeigniter.com/user_guide/general/hooks.html

С уважением, Рейн Гроот

1 голос
/ 17 июля 2009

Я не могу вам сильно помочь с тестированием, но я могу помочь вам расширить библиотеку CI.

Вы можете создать свой собственный MY_Loader класс внутри /application/libraries/MY_Loader.php.

<?php
  class MY_Loader extends CI_Loader {

    function view($view, $vars = array(), $return = FALSE) {
      echo 'My custom code goes here';
    }

  }

CodeIgniter увидит это автоматически. Просто вставьте функции, которые вы хотите заменить в исходной библиотеке. Все остальное будет использовать оригинал.

Для получения дополнительной информации посетите страницу руководства CI по созданию базовых системных классов .

0 голосов
/ 26 ноября 2013

Контроллер не должен содержать доменную логику, поэтому модульные тесты здесь не имеют смысла.

Вместо этого я бы протестировал контроллеры и представления с приемочными тестами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...