Модульное тестирование контроллеров

fixxxer

К.О.
Партнер клуба
И кстати нет ничего плохого в том, что сервис принимает instanceof Request для инициализации (не как instanceof Request но как instanceof Datasource).

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

Про chain/decorator тоже мысль интересная.
 

korchasa

LIMB infected
Плохое есть - зависимость он названий полей в html. У нас сервисы оперируют только предметной областью.

Имена шаблонов я бы тоже выбирал в контроллере, на основе данных от сервиса.
 

whirlwind

TDD infected, paranoid
А вот такой вопрос возник. У вас сервисы в единичном экземпляре хранят состояние для пользователя сервиса между обращениями, или они общие на весь проект независимо откуда вызов, или и то, и то?
 

korchasa

LIMB infected
Они stateless, т.е. второй вариант. Они инкапсулируют бизнес процесс, а модели - бизнес данные.

-~{}~ 26.10.10 19:01:

Они в принципе могут иметь стадии, например, регистрация пользователя (незарегистрирован - неподтвержден - подтвержден). Но данные они берут из модели пользователя. Да и интерфейс на разных стадиях обычно разный.
 

fixxxer

К.О.
Партнер клуба
>> Плохое есть - зависимость он названий полей в html.

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

-~{}~ 26.10.10 19:28:

Ну кстати почему обязательно stateless?

::construct($Dep1, $Dep2...)
->loadFrom(.....)
->doSmth(..)
->renderInto(View)

why not?
 

whirlwind

TDD infected, paranoid
korchasa а можешь показать какой нибудь свой контроллер, который через сервис лейер работает? Лучше 1 раз увидеть :)
 

korchasa

LIMB infected
Автор оригинала: whirlwind
korchasa а можешь показать какой нибудь свой контроллер, который через сервис лейер работает? Лучше 1 раз увидеть :)
PHP:
function doSimpleSearch()
{
  $this->useForm('search_form');
  $this->setFormDatasource($this->request);

  if(!$this->query = $this->request->get('query'))
    return;

  $page_number = $this->request->get('pager', 1);

  $service = new SimpleSearchService();

  $service->makeSearch($this->query);
  $this->items = $service->getMatchesForPage($page_number);
  $this->total_items = $service->getTotalMatchesCount();
  $this->items_limit = $service->getLimit();
}
 

whirlwind

TDD infected, paranoid
korchasa хм, очень интересно. То есть он сам через контекст запроса определяет какую модель ищем? Если так, то в тестах конечно вообще красота будет, если инстацирование через фабрику или локатор сделать. Спасибо.
 

korchasa

LIMB infected
whirlwind
Он для всех моделей ищет. И миксует результат. Это особенность поиска в этом проекте. Разница только в представлении результата.
 

whirlwind

TDD infected, paranoid
korchasa А критерии поиска он откуда берет? В сервисе прошито для каждого класса модели? Я просто не совсем понимаю, вроде ты говорил что про реквесты не знает, но я тут не вижу переброса параметров поиска с реквеста в сервис. Единственное могу предположить, что сервис все таки знает и модель и реквеста с нужными параметрами. Не?

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

korchasa

LIMB infected
Критерий поиска один - строка поиска query. Дальше он делает запрос к трем индексам сфинка, мержит их результаты, отсчитывает нужную страницу и строит коллекцию из объектов трех моделей.

-~{}~ 26.10.10 21:13:

Если бы типов поиска было несколько, то я бы это сделал либо разными методами а ля makeSearchForMember(), либо явным указанием типа через константу makeSearch($query, SearchService::MEMBERS)
 

whirlwind

TDD infected, paranoid
Re: Модульное тестирование контроллеров

Было
Контроллер: http://pastebin.com/SjXcGck9
Тест: http://pastebin.com/fWNHca1W

Стало
Контроллер: http://pastebin.com/YqeAHvnc
Тест: http://pastebin.com/LhXM0ajB


Вроде получше, но это только тут. Ведь добавились еще классы которые тоже с тестами. А еще добавилась измена, что где то не учли исключения из добавленных слоев и случаев, когда юзер будет видеть "фатал еррор, обратитесь к одмину" теперь потенциально больше.
В целом, особой разницы не заметил. Что здесь стабы приходится настраивать, что в старом варианте. Одного я все еще не понимаю - как у вас получаются контроллеры настолько тупые, что их и тестировать не надо? Кому не жалко примера теста тупого контроллера, который обрабатывает более одного поля и более одного варианта развития событий, буду очень признателен если выложите.
 

korchasa

LIMB infected
whirlwind
На вскидку, я бы ввел AccessService и запихнул все проверки а ля $user->getStatus() == EveUser::STATUS_BANNED в него, через метод isUserBanned(). Тогда для тестов контроллера пришлось бы делать меньше стабов.
 
Сверху