Я хочу как можно больше использовать Test Driven Development – это отличный способ работы.
Меня беспокоит тот факт, что контроллеры Symfony2 создают и возвращают новый объект Response
.
Я хочу, чтобы я мог тестировать контроллер отдельно.
Как ты делаешь это?
Является ли ответ на создание контроллера как обычного обычного PHP-объекта, зарегистрировать его как службу и использовать Injection Dependency для передачи в него нового объекта Response
(или фабрики Response
)?
Обычно ваш контроллер подключает разные объекты и подключает их в правильном порядке. Возможно, он называет репозиторий, читает некоторые объекты и возвращает их через метод рендеринга. Может быть, он называет некоторых других Хендлеров / Менеджеров, которые делают вещи.
Это означает, что контроллер является компонентом высокого уровня. Чаще всего это указывает на то, что функциональные тесты в порядке, а не модульные тесты. Вы не должны стремиться получать 100% -ный охват кода с помощью модульных тестов. Возможно, вы можете так думать: если вы тестируете все, что вызывает контроллер (модель, валидация, форма, репозиторий), что может пойти не так? В большинстве случаев это то, что вы наблюдаете только при использовании всех реальных классов, участвующих в производстве.
Я хочу также отметить, что TDD не означает, что все должно быть проверено на единицу. Это нормально, чтобы иметь некоторые функциональные тесты для кода высокого уровня. Как сказано, если вы тестируете низкоуровневые компоненты с помощью единичных тестов, вы должны только проверить, как они работают вместе, что вы не можете тестировать с помощью mocks, потому что вы скажете, что mocks указывает на возвращаемое значение.
Если ваш контроллер делает больше, чем подключать части системы вместе, вы должны подумать о том, чтобы реорганизовать материал на более низкоуровневые классы, которые вы можете тестировать с помощью модульных тестов.
Поэтому я хотел бы использовать функциональные тесты для тестирования ваших контроллеров и использования модульных тестов для тестирования ваших моделей и вашей бизнес-логики.
Если вы боретесь с функциональными тестами, вы можете прочитать следующее:
Используйте mocks для выделения моделей и других объектов из логики основного контроллера, см. http://www.phpunit.de/manual/3.7/en/test-doubles.html#test-doubles.mock-objects
Я думаю, что в более старых версиях вы могли бы издеваться над целым классом, но с последним phpunit 3.6.10, который, как мне кажется, не работает. Так что, я думаю, вы остаетесь с шаблоном инъекции depency
class objss{ function ss(){ $x = new zz(); var_dump($x->z()); } } class MoTest extends PHPUnit_Framework_TestCase{ public function setUp(){ } public function testA(){ $class = $this->getMock('zzMock', array('z'), array(), 'zz'); $class->expects($this->any())->method('z')->will($this->returnValue('2')); $obj = new objss(); $this->assertEquals('2', $obj->ss()); } }
Обновите свои контроллеры для обслуживания: http://symfony.com/doc/current/cookbook/controller/service.html.
Затем вы можете легко их протестировать.
Конечно (как уже упоминалось другими) вы можете использовать WebTestCase
как описано здесь: http://symfony.com/doc/current/book/testing.html#functional-tests
Льюис. Я думал, что приеду сюда. В приведенном выше подходе вы копируете лучшую часть своей логики действий в своих тестах. В этом нет ничего плохого, многие фреймворки (особенно RSPEC в Rails) на самом деле предлагают вам выполнять как модульные тесты на объектах Controller, так и функциональные тесты. Однако, учитывая ваш пример, я думаю, что пропустил бы модульный тест и пошел бы на функциональный подход.
Моей мыслью является создание изолированной среды, запуск теста и проверка на наличие побочных эффектов и прямой результат. Если вы дойдете до точки, где большая часть вашего теста изолирует метод, то это, вероятно, время либо для другого подхода к тестированию, либо для другого подхода к написанию вашего класса. Учитывая, что это контроллер, и по своей природе они склеивают разные части стека, я бы создал вашу песочницу дальше по стеку. В частности, я бы использовал такой подход:
https://github.com/PolishSymfonyCommunity/SymfonyMockerContainer
Отлично работает для меня 🙂