Тестирование контроллеров
Тестирование контроллеров упрощено с помощью нескольких новых вспомогательных классов и трейтов. При тестировании контроллеров вы можете выполнить код внутри контроллера без предварительного запуска всего процесса загрузки приложения. Часто использование инструментов тестирования функциональности будет проще, но эта функциональность предоставляется на случай необходимости.
Примечание
Поскольку весь фреймворк не был загружен, иногда тестирование контроллера таким способом невозможно.
Вспомогательный трейт
Для включения тестирования контроллеров вам необходимо использовать трейт ControllerTestTrait в ваших тестах:
<?php
namespace CodeIgniter;
use CodeIgniter\Test\ControllerTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
class TestControllerA extends CIUnitTestCase
{
use ControllerTestTrait, DatabaseTestTrait;
}
После включения трейта вы можете начать настройку среды, включая классы запроса и ответа, тело запроса, URI и многое другое. Вы указываете используемый контроллер с помощью метода controller(), передавая полное имя класса вашего контроллера. Наконец, вызовите метод execute() с именем метода для выполнения в качестве параметра:
<?php
namespace CodeIgniter;
use CodeIgniter\Test\ControllerTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
class TestControllerA extends CIUnitTestCase
{
use ControllerTestTrait, DatabaseTestTrait;
public function testShowCategories()
{
$result = $this->withURI('http://example.com/categories')
->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
$this->assertTrue($result->isOK());
}
}
Вспомогательные методы
controller($class)
Указывает имя класса контроллера для тестирования. Первый параметр должен быть полным именем класса (включая пространство имен):
$this->controller(\App\Controllers\ForumController::class);
execute($method)
Выполняет указанный метод внутри контроллера. Единственный параметр — имя метода для выполнения:
$results = $this->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
Это возвращает новый вспомогательный класс, который предоставляет ряд процедур для проверки самого ответа. Подробности см. ниже.
withConfig($config)
Позволяет передать измененную версию ConfigApp.php для тестирования с различными настройками:
$config = new Config\App();
$config->appTimezone = 'America/Chicago';
$results = $this->withConfig($config)
->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
Если вы не укажете ее, будет использоваться файл конфигурации приложения App.
withRequest($request)
Позволяет предоставить экземпляр IncomingRequest, настроенный для ваших потребностей в тестировании:
$request = new CodeIgniter\HTTP\IncomingRequest(new Config\App(), new URI('http://example.com'));
$request->setLocale($locale);
$results = $this->withRequest($request)
->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
Если вы не укажете его, в ваш контроллер будет передан новый экземпляр IncomingRequest с значениями по умолчанию приложения.
withResponse($response)
Позволяет предоставить экземпляр Response:
$response = new CodeIgniter\HTTP\Response(new Config\App());
$results = $this->withResponse($response)
->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
Если вы не укажете его, в ваш контроллер будет передан новый экземпляр Response со значениями по умолчанию приложения.
withLogger($logger)
Позволяет предоставить экземпляр Logger:
$logger = new CodeIgniter\Log\Handlers\FileHandler();
$results = $this->withResponse($response)
->withLogger($logger)
->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
Если вы не укажете его, в ваш контроллер будет передан новый экземпляр Logger со значениями по умолчанию конфигурации.
withURI($uri)
Позволяет предоставить новый URI, который имитирует URL, посещенный клиентом при запуске этого контроллера. Это полезно, если вам нужно проверить сегменты URI внутри контроллера. Единственный параметр — строка, представляющая допустимый URI:
$results = $this->withURI('http://example.com/forums/categories')
->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
Рекомендуется всегда указывать URI во время тестирования, чтобы избежать неожиданностей.
withBody($body)
Позволяет предоставить настраиваемое тело для запроса. Это может быть полезно при тестировании API-контроллеров, где вам необходимо установить значение JSON в качестве тела. Единственный параметр — строка, представляющая тело запроса:
$body = json_encode(['foo' => 'bar']);
$results = $this->withBody($body)
->controller(\App\Controllers\ForumController::class)
->execute('showCategories');
Проверка ответа
ControllerTestTrait::execute() возвращает экземпляр TestResponse. См. Тестирование ответов, как использовать этот класс для выполнения дополнительных утверждений и проверок в ваших тестовых случаях.
Тестирование фильтров
Аналогично тестированию контроллеров, фреймворк предоставляет инструменты для создания тестов на пользовательские фильтры и их использование в вашем проекте при маршрутизации.
Вспомогательный трейт
Как и в случае с тестером контроллеров, вам необходимо включить FilterTestTrait в ваши тестовые сценарии, чтобы включить эти функции:
<?php
namespace CodeIgniter;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FilterTestTrait;
class FilterTestCase extends CIUnitTestCase
{
use FilterTestTrait;
}
Настройка
Из-за логического перекрытия с тестированием контроллеров FilterTestTrait разработан для совместной работы с ControllerTestTrait, если вам нужно оба в одном классе. После включения трейта CIUnitTestCase обнаружит свой метод setUp и подготовит все компоненты, необходимые для ваших тестов. Если вам нужна специальная конфигурация, вы можете изменить любые свойства перед вызовом поддерживающих методов:
-
$requestПодготовленная версия стандартной службыIncomingRequest -
$responseПодготовленная версия стандартной службыResponseInterface -
$filtersConfigСтандартная конфигурацияConfig\Filters(обратите внимание: обнаружение обрабатываетсяFilters, поэтому это не будет включать псевдонимы модулей) -
$filtersЭкземплярCodeIgniter\Filters\Filters, использующий три вышеуказанных компонента -
$collectionПодготовленная версияRouteCollection, которая включает обнаружениеConfig\Routes
Стандартная конфигурация, как правило, лучше всего подходит для тестирования, так как она наиболее точно имитирует «живой» проект, но (например), если вы хотите смоделировать случайное срабатывание фильтра на неотфильтрованном маршруте, вы можете добавить его в конфигурацию:
class FilterTestCase extends CIUnitTestCase
{
use FilterTestTrait;
protected function testFilterFailsOnAdminRoute()
{
$this->filtersConfig->globals['before'] = ['admin-only-filter'];
$this->assertHasFilters('unfiltered/route', 'before');
}
...
Проверка маршрутов
Первый вспомогательный метод — getFiltersForRoute(), который будет моделировать предоставленный маршрут и возвращать список всех фильтров (по их псевдонимам), которые должны были запуститься для данного расположения («перед» или «после»), не выполняя фактически код контроллера или маршрутизации. Это значительно улучшает производительность по сравнению с контроллером и HTTP-тестированием.
-
getFiltersForRoute($route, $position) -
Параметры: - $route (string) — URI для проверки
- $position (string) — метод фильтра для проверки, «перед» или «после»
Возвращает: Псевдонимы каждого фильтра, который должен был запуститься
Тип возвращаемого значения: string[]
Пример использования:
$result = $this->getFiltersForRoute('/', 'after'); // ['toolbar']
Вызов методов фильтра
Свойства, описанные в Настройках, настроены для максимальной производительности без вмешательства или помех от других тестов. Следующий вспомогательный метод вернет вызываемый метод для безопасного тестирования кода вашего фильтра и проверки результатов.
-
getFilterCaller($filter, $position) -
Параметры: - $filter (FilterInterface|string) — экземпляр фильтра, класс или псевдоним
- $position (string) — метод фильтра для выполнения, «перед» или «после»
Возвращает: Вызываемый метод для запуска имитированного события фильтра
Тип возвращаемого значения: Closure
Пример использования:
protected function testUnauthorizedAccessRedirects() { $caller = $this->getFilterCaller('permission', 'before'); $result = $caller('MayEditWidgets'); $this->assertInstanceOf('CodeIgniter\HTTP\RedirectResponse', $result); }Обратите внимание, как
Closureможет принимать входные параметры, которые передаются в ваш метод фильтра.
Утверждения
В дополнение к вспомогательным методам выше, FilterTestTrait также поставляется с некоторыми утверждениями для упрощения ваших тестовых методов.
Метод assertFilter() проверяет, что для данного маршрута в указанном месте используется фильтр (по его псевдониму):
// Make sure users are logged in before checking their account
$this->assertFilter('users/account', 'before', 'login');
Метод assertNotFilter() проверяет, что для данного маршрута в указанном месте не используется фильтр (по его псевдониму):
// Make sure API calls do not try to use the Debug Toolbar
$this->assertNotFilter('api/v1/widgets', 'after', 'toolbar');
Метод assertHasFilters() проверяет, что для данного маршрута в указанном месте установлен хотя бы один фильтр:
// Make sure that filters are enabled
$this->assertHasFilters('filtered/route', 'after');
Метод assertNotHasFilters() проверяет, что для данного маршрута в указанном месте фильтры не установлены:
// Make sure no filters run for our static pages
$this->assertNotHasFilters('about/contact', 'before');
© 2014–2020 British Columbia Institute of Technology
Licensed under the MIT License.
https://codeigniter.com/user_guide/testing/controllers.html