Я создал очень простой контроллер REST в Symony2 с вставкой / обновлениями / удалениями базы данных в действиях контроллера.
Есть ли хороший способ написать тесты модуляции / интеграции для этих действий контроллера без загрязнения производственной базы данных? Должен ли я работать с разными средами – или есть ли предлагаемый путь от поставщика инфраструктуры для этого?
Текущий контроллер Пример:
public function postAction() { $json = $this->getRequest()->getContent(); $params = json_decode($json); $name = $params->name; $description = $params->description; $sandbox = new Sandbox(); $sandbox->setName($name); $sandbox->setDescription($description); $em = $this->getDoctrine()->getManager(); $em->persist($sandbox); $em->flush(); $response = new Response('/sandbox/'.$sandbox->getId()); $response->setStatusCode(201); return $response; }
Текущий тестовый пример:
class SandboxControllerTest extends WebTestCase { public function testRest() { $client = static::createClient(); $crawler = $client->request('POST', '/service/sandbox', array(), array(), array(), json_encode(array('name' => 'TestMe', 'description' => 'TestDesc'))); $this->assertEquals( 201, $client->getResponse()->getStatusCode() ); } }
На мой взгляд, вы обязательно должны избегать базы данных изменений с вашими тестами.
Моим любимым способом добиться этого является интуитивно понятный менеджер, находящийся в тестовом клиенте. Например:
public function testRest() { // create entity manager mock $entityManagerMock = $this->getMockBuilder('Doctrine\ORM\EntityManager') ->setMethods(array('persist', 'flush')) ->disableOriginalConstructor() ->getMock(); // now you can get some assertions if you want, eg.: $entityManagerMock->expects($this->once()) ->method('flush'); // next you need inject your mocked em into client's service container $client = static::createClient(); $client->getContainer()->set('doctrine.orm.default_entity_manager', $entityManagerMock); // then you just do testing as usual $crawler = $client->request('POST', '/service/sandbox', array(), array(), array(), json_encode(array('name' => 'TestMe', 'description' => 'TestDesc'))); $this->assertEquals( 201, $client->getResponse()->getStatusCode() ); }
Одна вещь с этим решением, о котором вы должны знать, заключается в том, что перед каждым запросом вы должны вводить свою издеваемую службу. Это происходит потому, что клиент перезагружает ядро между каждым запросом (что означает, что контейнер также перестраивается).
редактировать:
Мой подход GET в тестах контроллера заключается в том, что я могу издеваться над репозиториями объектов и т. Д., Чтобы заглушить каждый процесс получения данных из db, но это большая работа, и это не очень удобно, поэтому я предпочитаю в этом случае (я имею в виду только, если мы говорим о тестировании контроллера), фактически получая реальные данные из db. По реальным данным я имею в виду данные, созданные с помощью приборов доктрины. И пока мы не меняем базу данных, мы можем зависеть от приборов.
Но если мы говорим об изменении данных внутри db (методы POST / PUT / DELETE), я всегда использую mocks. Если вы будете использовать em mock и зададите соответствующие ожидания по методам «perist» и «flush», вы можете быть уверены, что данные правильно созданы / обновлены / удалены фактически без каких-либо изменений в базе данных.
Вот что я делаю
в тестовом классе добавьте статическую переменную $ kernel и создайте функцию, загружающую ядро в тестовый режим
protected static $kernel; protected static $container; public static function setUpBeforeClass() { self::$kernel = new \AppKernel('test', true); self::$kernel->boot(); self::$container = self::$kernel->getContainer(); }
И как первая строка тестовой функции, вызовите self:setUpBeforeClass()
Это заставляет symfony загружать конфигурационный файл config_test.yml, и вы можете определить другое соединение с базой данных там
Хороший способ сделать это, особенно если вам нужно иметь некоторые тестовые данные в вашей базе данных, используется отдельная база данных SQLite вместе с DoctrineFixturesBundle.
Чистый способ настроить светильники и тесты
Убедитесь, что расширение SQLite активировано в вашем php