2017-02-17 18 views
1

Я пытаюсь написать функциональный тест для моего проекта в Symfony2. Я хотел бы проверить, может ли пользователь получить доступ к странице, заполнить форму и отправить ее. Я пытаюсь найти способ отбросить базу данных до состояния, которое было до теста. Я нашел вспомогательный класс I, слегка измененный в https://gist.github.com/Vp3n/5472509, который расширяет методы WebTestCase и перегрузки setUp и tearDown. Вот моды, которые я сделал для того, чтобы попытаться сделать это работает:Как откат транзакций при выполнении функциональных тестов с помощью Symfony2

/** 
* Before each test we start a new transaction 
* everything done in the test will be canceled ensuring isolation et speed 
*/ 
protected function setUp() 
{ 
    parent::setUp(); 
    $this->client = $this->createClient(); 
    $this->em = static::$kernel->getContainer() 
     ->get('doctrine') 
     ->getManager(); 
    $this->em->getConnection()->beginTransaction(); 
    $this->em->getConnection()->setAutoCommit(false); 
} 
/** 
* After each test, a rollback reset the state of 
* the database 
*/ 
protected function tearDown() 
{ 
    parent::tearDown(); 
    if($this->em->getConnection()->isTransactionActive()){ 
     echo 'existing transactions'; 
     $this->em->getConnection()->rollback(); 
     $this->em->close(); 
    } 
} 

Когда я запускаю тесты, он признает для существующих операций, но откат не выполняется и модификации сохраняются.

Test Logs:

Runtime:  PHP 5.6.15 

.existing transactions.  2/2 (100%)existing transactions                      

Time: 5.47 seconds, Memory: 24.50MB 

OK (2 tests, 5 assertions) 

Что я делаю неправильно? Это даже лучшая практика? Любая помощь будет оценена :)

EDIT

Это работает для меня:

abstract class DatabaseWebTest extends WebTestCase { 
/** 
* helper to acccess EntityManager 
*/ 
protected $em; 
/** 
* Helper to access test Client 
*/ 
protected $client; 
/** 
* Before each test we start a new transaction 
* everything done in the test will be canceled ensuring isolation et speed 
*/ 
protected function setUp() 
{ 
    parent::setUp(); 

    $this->client = $this->createClient(['environment' => 'test'], array(
     'PHP_AUTH_USER' => 'user', 
     'PHP_AUTH_PW' => 'password', 
     )); 
    $this->client->disableReboot(); 
    $this->em = $this->client->getContainer()->get('doctrine.orm.entity_manager');   
    $this->em->beginTransaction(); 
    $this->em->getConnection()->setAutoCommit(false); 
} 
/** 
* After each test, a rollback reset the state of 
* the database 
*/ 
protected function tearDown() 
{ 
    parent::tearDown(); 

    if($this->em->getConnection()->isTransactionActive()) { 
     $this->em->rollback(); 
    }   
} 

}

ответ

3

Вы делаете более одного запроса с помощью Client? Если это так, возможно, проблема заключается в том, что клиент завершает работу ядра после выполнения одного запроса. Но вы можете отключить, что с $this->client->disableReboot() Так что этот фрагмент кода необходимо идемпотентным:

public function setUp() 
{ 
    $this->client = $this->createClient(['environment' => 'test']); 
    $this->client->disableReboot(); 
    $this->em = $this->client->getContainer()->get('doctrine.orm.entity_manager'); 
    $this->em->beginTransaction(); 
} 

public function tearDown() 
{ 
    $this->em->rollback(); 
} 

public function testCreateNewEntity() 
{ 
    $this->client->request('GET', '/create/entity/form'); 
    $this->client->request('POST', '/create/entity/unique/123'); 
} 
+0

Извините за поздний ответ. Действительно, проблема заключалась в том, что транзакции не были разделены из-за сброса ядра между каждым тестом. Так disableReboot() сделал трюк вместе с setAutoCommit (false). Спасибо за ваш ответ и ответ. – EtienneDh

1

Вы можете использовать тестовую базу данных самоотверженности для тестирования

Другого варианта использует Codeception. Это комплект модулей тестирования, который работает с Symfony. Если вы используете это, вы можете настроить его на использование тестовой базы данных, а затем «очистить ее» после каждого цикла тестирования.
Пример yaml configuartion для этого был бы чем-то вроде: cleanup: true делает то, что вы хотите;

class_name: UnitTester 
modules: 
    enabled: 
     - Asserts 
     - Symfony2: 
      app_path: '../../app' 
      var_path: '../../app' 
      environment: 'test' 
     - Doctrine2: 
      depends: Symfony2 
      cleanup: true 
     - \AppBundle\Helper\Unit 
+0

Спасибо, я посмотрю на это. Altho Я не уверен, что мне разрешено использовать Bundle, который не был разрешен в первую очередь для этого проекта. – EtienneDh

2

Я бы рекомендовал использовать этот пакет: https://packagist.org/packages/dama/doctrine-test-bundle

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