使用数据夹具管理实体ID

时间:2017-01-22 15:45:53

标签: doctrine-orm doctrine fixtures

我遇到了Doctrine Data Fixtures的一个问题:当我使用fixture来插入一些数据来运行验收测试时,我能否以某种方式确保持久存在特定实体并保留特定ID?

例如,我创建了几个示例用户,然后运行验证测试来编辑其中一个用户。我需要知道此测试用例的用户ID。 处理这个问题的最佳做法是什么? 是否可以对由夹具创建的某些实体的ID进行硬编码,还是应该将生成的ID存储到单独的表,文件等中以查找所请求的实体?或者还有其他最佳做法吗?

提前致谢。

1 个答案:

答案 0 :(得分: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();

此外,您可以引用其所有属性,而不仅仅是ID。因此,如果你想说声明,你的api返回了正确的类别,你就可以这样做。

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

如果您只想为一个测试用例修改数据,请使用fixture的属性修改数据库,然后再清除EM,这样您就不会在实体中创建已填充的身份映射的副作用管理器。

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

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

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