2017-01-22 15 views
0

У меня возникла проблема с устройствами Doctrine Data Fixtures: когда я вставляю некоторые данные, используя приборы для запуска приемочных тестов, могу ли я каким-то образом обеспечить сохранение определенных объектов с определенным идентификатором?Управление идентификаторами сущностей с приборами данных

Например, я создаю несколько примерных пользователей, а затем запускаю приемочный тест, редактируя одного из пользователей. Мне нужно знать идентификатор пользователя для этого тестового примера. Какова наилучшая практика для этого? Возможно ли присвоить идентификаторы жесткого кода некоторым объектам, созданным приборами, или я должен хранить сгенерированные идентификаторы в отдельной таблице, файле и т. Д., Чтобы найти запрошенный объект? или есть ли другая лучшая практика?

Заранее спасибо.

+0

Вы не помечать вопрос с Symfony, но прочитав здесь: https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html#sharing-objects-between-fixtures может дать вам некоторые идеи. – Cerad

+0

Ну, я не потому, что я не работаю с Symfony там :) Я использую Doctrine также для Nette framework. Тем не менее, я, наконец, оказался в этом подходе Symfony, поэтому спасибо :) – amik

ответ

4

В нашем приложении мы устанавливаем объекты в статические свойства этих светильников, поэтому их можно легко использовать из тестов.

class CategoryTestFixture 
    extends \Doctrine\Common\DataFixtures\AbstractFixture 
    implements 
     \Doctrine\Common\DataFixtures\OrderedFixtureInterface, 
     \Symfony\Component\DependencyInjection\ContainerAwareInterface 
{ 

    /** @var \My\Category */ 
    public static $fooCategory; 

    /** @var \My\Category */ 
    public static $barCategory; 

    /** @var \Symfony\Component\DependencyInjection\ContainerInterface */ 
    private $container; 

    public function load(ObjectManager $manager) 
    { 
     self::$fooCategory = new Category('Foo'); 
     $entityManager->persist(self::$fooCategory); 

     self::$barCategory = new Category('Bar'); 
     $entityManager->persist(self::$barCategory); 

     $entityManager->flush(); 
    } 

    // you can inject the container, 
    // so you can use your Facades in fixtures 

    public function getContainer(): ContainerInterface 
    { 
     return $this->container; 
    } 

    public function setContainer(ContainerInterface $container = null) 
    { 
     $this->container = $container; 
    } 

} 

Есть несколько важных правил для этого:

  • Убедитесь, что вы не вызываете $em->clear() в ваших светильниках, так что вы можете напрямую использовать объекты в других классах светильников.
  • Звоните $em->clear() после того, как светильники загружены, поэтому они не влияют на ваши тесты.
  • Перед каждым тестом сделайте копию подготовленной базы данных и используйте эту копию для своих тестов, а не «базу данных шаблонов». Таким образом, вы можете безопасно модифицировать данные. Его можно дополнительно оптимизировать, но это наиболее простое решение.
  • Не сливайте и не пытайтесь зарегистрировать как управляемые оригинальные светильники в своих тестах.

Теперь, когда вы создали светильники, можно использовать их как этот

$id = CategoryTestFixture::$barCategory->getId(); 

Кроме того, вы можете ссылаться на все их свойства, а не только идентификаторы. Поэтому, если вы скажете, что хотите утверждать, что ваш api вернул правильные категории, вы можете сделать это вот так.

$this->assertArraySubset([ 
    [ 
     'id' => CategoryTestFixture::$fooCategory->getId(), 
     'name' => CategoryTestFixture::$fooCategory->getName(), 
    ], 
    [ 
     'id' => CategoryTestFixture::$barCategory->getId(), 
     'name' => CategoryTestFixture::$barCategory->getName(), 
    ] 
], $apiResponseData); 

и если вы хотите изменить данные только для одного TestCase, используйте свойство светильника, чтобы изменить базу данных, а затем ясно EM aftewards, так что вы не создаете побочные эффекты уже заселенный тождественный в диспетчер объектов.

$barCategory = $entityManager->find(
    Category::class, 
    CategoryTestFixture::$barCategory->getId() 
); 

$barCategory->setName('Another name'); 

$entityManager->flush(); 
$entityManager->clear(); 
+0

Интересная идея, но я не вижу, как это лучше, чем подход ссылок Symfony. Я также не совсем понимаю, как очистка EM помогает, не должны уже загруженные объекты быть правильно отображены Doctrine, так что, если я изменю ее из ссылки, все остальные ссылки («referring variables») указывают на то же, измененное организация? – amik