Тесты Symfony2: проблема с приборами и внешними ключами
Я разрабатываю проект с Symfony и Doctrine, и у меня есть проблема с моими тестами. Я использую Fixtures для загрузки данных для тестов, и некоторые из моих сущностей имеют ассоциации между ними. При первом запуске моих тестов с пустыми таблицами БД тесты проходят без ошибок. Но когда я снова запускаю тест, я получаю сообщение об ошибке:
Doctrine \ DBAL \ DBALException: возникла исключительная ситуация при выполнении команды "DELETE FROM Ent":
SQLSTATE [23000]: Нарушение ограничения целостности: 1451 Не удается удалить или обновить родительскую строку: ограничение внешнего ключа не выполняется (
my_db
,Ent
, ОГРАНИЧЕНИЕFK_FE5D1D1E727ACA70
ИНОСТРАННЫЙ КЛЮЧ (parent_id
) РЕКОМЕНДАЦИИEnt
(id
))
Причина ошибки очевидна: невозможно удалить строку, если другая строка ссылается на нее через внешний ключ.
Если я сначала усекаю таблицу, отключив ограничения внешнего ключа, и снова запускаю тест с пустой таблицей, тесты снова успешны. Но я должен повторять это каждый раз, когда я запускаю тесты.
Таким образом, вопрос: есть ли способ заставить Symfony или PHPUnit обрабатывать это автоматически?
Спасибо!
РЕДАКТИРОВАТЬ: я забыл упомянуть, что я использую класс Liip\FunctionalTestBundle\Test\WebTestCase.
2 ответа
Я закончил тем, что расширил WebTestCase как предложено Nextar. Спасибо!
Это код:
<?php
namespace Acme\MyBundle\Tests\Controller;
use Liip\FunctionalTestBundle\Test\WebTestCase;
class MyWebTestCase extends WebTestCase {
protected function loadFixtures(array $classNames, $omName = null, $registryName = 'doctrine', $purgeMode = null) {
$this->getContainer()->get('doctrine')->getManager()->getConnection()->query(sprintf('SET FOREIGN_KEY_CHECKS=0'));
$result = parent::loadFixtures($classNames, $omName, $registryName, $purgeMode);
$this->getContainer()->get('doctrine')->getManager()->getConnection()->query(sprintf('SET FOREIGN_KEY_CHECKS=1'));
return $result;
}
}
Есть способ сделать это, вы должны написать свой собственный WebTestCase, который расширяет тот, который предоставляется Symfony
Symfony\Bundle\FrameworkBundle\Test\WebTestCase
В методе loadFixtures вашего собственного WebTestCase вы просто используете командный компонент для:
- Удалить базу данных
- Создать схему
- загрузить светильники
Не забудь! Если вы выполняете команды, определите --env как тест! В противном случае вы бросите свою базу данных.
Затем в каждом функциональном тесте вся база данных будет перестроена, и все приборы будут загружены.