2012-04-12 4 views
24

Я хочу как можно больше использовать Test Driven Development - это отличный способ работы.Как я могу протестировать контроллер Symfony2?

Меня беспокоит то, что контроллеры Symfony2 создают и возвращают новый объект Response.

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

Как вы это делаете?

Является ли ответ на создание контроллера как обычного обычного объекта PHP, зарегистрировать его как услугу и использовать инъекцию зависимостей для передачи нового объекта Response (или фабрики Response)?

+2

Что именно проблема с этим возвратом объекта 'Response'? –

+0

Ничего. Мне просто не нравится тот факт, что объект Response создается в контроллере. Я твердо верю в Injection Dependency, и мне не нравится видеть «новое» ключевое слово в чем-либо, кроме контейнера DI. Может быть, эта вера неверна. –

ответ

51

Как правило, ваш контроллер подключает разные объекты и подключает их в правильном порядке. Возможно, он называет репозиторий, читает некоторые объекты и возвращает их через метод рендеринга. Может быть, он называет некоторых других Хендлеров/Менеджеров, которые делают вещи.

Это означает, что контроллер является компонентом высокого уровня. Чаще всего это указывает на то, что функциональные тесты в порядке, а не модульные тесты. Вы не должны стремиться получать 100% -ный охват кода с помощью модульных тестов. Возможно, вы можете так думать: если вы тестируете все, что вызывает контроллер (модель, валидация, форма, репозиторий), что может пойти не так? В большинстве случаев это то, что вы наблюдаете только при использовании всех реальных классов, участвующих в производстве.

Я хочу также отметить, что TDD не означает, что все должно быть проверено на единицу. Это нормально, чтобы иметь некоторые функциональные тесты для кода высокого уровня. Как сказано, если вы тестируете низкоуровневые компоненты с помощью единичных тестов, вы должны только проверить, как они работают вместе, что вы не можете тестировать с помощью mocks, потому что вы скажете, что mocks указывает на возвращаемое значение.

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

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

Если вы боретесь с функциональными пробами, вы можете прочитать следующее:

+0

Хорошо. Я думал, что, поскольку Контроллер был классом, он также должен был быть проверен модулем. Мне не нравится идея написания кода перед написанием тестов, поэтому мне было интересно, есть ли способ реорганизовать способ использования контроллеров, чтобы иметь возможность тестировать их. Думаю, я все еще могу работать с TDD, написав функциональные тесты, прежде чем писать контроллер. –

2

Использования издевается изолировать модели и другие объекты из логики основного метода контроллера, см 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()); 
    } 
} 
+0

Totaly - но эти объекты (включая объект Response) будут созданы в контроллере. Если я не использую контейнер DI, чтобы предоставить модели и другие вещи для контроллеров. Возможно, я мог бы создать заводскую службу Response и получить его из контейнера DI - таким образом, он (контейнер DI и фабрика) может быть изделен за тестирование класса Controller изолированно. –

0

Льюис - Я думал, что прыгать здесь. В приведенном выше подходе вы копируете лучшую часть своей логики действий в своих тестах. В этом нет ничего плохого, многие фреймворки (особенно RSPEC в Rails) на самом деле предлагают вам выполнять как модульные тесты на объектах Controller, так и функциональные тесты. Однако, учитывая ваш пример, я думаю, что пропустил бы модульный тест и пошел бы на функциональный подход.

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

https://github.com/PolishSymfonyCommunity/SymfonyMockerContainer

работал большой для меня :)

1

модульного тестирования

реорганизовать контроллеры для служб: http://symfony.com/doc/current/cookbook/controller/service.html

Тогда вы могут легко их протестировать.

Функциональное тестирование

Конечно (как уже было сказано другими), вы можете использовать WebTestCase, как описано здесь: http://symfony.com/doc/current/book/testing.html#functional-tests

+0

Определение контроллеров как услуг официально не рекомендовано Symfony. Они используются некоторыми разработчиками для очень конкретных случаев использования, таких как DDD (доменный дизайн) и приложения с гексагональной архитектурой. –

+0

Кто это говорит? https://symfony.com/doc/current/controller/service.html Про в массовом порядке con в своей собственной документации. Я уверен, что контроллеры, поскольку службы будут поддерживаться в будущих версиях symfony, поэтому я бы не стал слишком беспокоиться о том, что это «официально не рекомендуется». –

Смежные вопросы