在Symfony测试环境中加载Doctrine Lazy

时间:2013-08-16 07:53:38

标签: php symfony doctrine-orm

我写了一个非常复杂的类,我想测试一些功能方面。

因此我使用symfony中的WebTestCase,并针对自我实现的导入进行测试,其中我依赖于doctrine的延迟加载。我想将数据导入为新行,这在两个环境中都可以正常工作,或者更新现有数据。在后一种情况下,我想加载给定的包,并获取目录(延迟加载)。

这部分在开发环境中工作正常,但测试在测试环境中失败。我正在使用symfony2(标准版)。在这里你可以看到我正在使用的测试

<?php
namespace Sulu\Bundle\TranslateBundle\Tests\Translate;

use Sulu\Bundle\CoreBundle\Tests\DatabaseTestCase;
use Sulu\Bundle\TranslateBundle\Translate\Import;

class ImportTest extends DatabaseTestCase
{
    /**
     * @var Import
     */
    protected $import;

    /**
     * @var array
     */
    protected static $entities;

    public function setUp()
    {
        $this->setUpSchema();

        $this->import = new Import(self::$em);
    }

    public function tearDown()
    {
        parent::tearDown();
        self::$tool->dropSchema(self::$entities);
    }

    public function setUpSchema()
    {
        self::$entities = array(
            self::$em->getClassMetadata('Sulu\Bundle\TranslateBundle\Entity\Catalogue'),
            self::$em->getClassMetadata('Sulu\Bundle\TranslateBundle\Entity\Code'),
            self::$em->getClassMetadata('Sulu\Bundle\TranslateBundle\Entity\Location'),
            self::$em->getClassMetadata('Sulu\Bundle\TranslateBundle\Entity\Package'),
            self::$em->getClassMetadata('Sulu\Bundle\TranslateBundle\Entity\Translation'),
        );

        self::$tool->createSchema(self::$entities);
    }

    public function testXliff()
    {
        // test usual import
        $this->import->setFile(__DIR__ . '/../Fixtures/import.xliff');
        $this->import->setName('Import');
        $this->import->setFormat(Import::XLIFF);
        $this->import->setLocale('de');
        $this->import->execute();

        $package = self::$em->getRepository('SuluTranslateBundle:Package')->find(1);
        $this->assertEquals(1, $package->getId());
        $this->assertEquals('Import', $package->getName());

        $catalogue = self::$em->getRepository('SuluTranslateBundle:Catalogue')->find(1);
        $this->assertEquals(1, $catalogue->getId());
        $this->assertEquals('de', $catalogue->getLocale());

        $codes = self::$em->getRepository('SuluTranslateBundle:Code')->findAll();
        $this->assertEquals(1, $codes[0]->getId());
        $this->assertEquals('sulu.great', $codes[0]->getCode());
        $this->assertEquals(true, $codes[0]->getBackend());
        $this->assertEquals(true, $codes[0]->getFrontend());
        $this->assertEquals(null, $codes[0]->getLength());
        $this->assertEquals(2, $codes[1]->getId());
        $this->assertEquals('sulu.open', $codes[1]->getCode());
        $this->assertEquals(true, $codes[1]->getBackend());
        $this->assertEquals(true, $codes[1]->getFrontend());
        $this->assertEquals(null, $codes[1]->getLength());

        $translations = self::$em->getRepository('SuluTranslateBundle:Translation')->findAll();
        $this->assertEquals('Sulu ist toll!', $translations[0]->getValue());
        $this->assertEquals('Sulu ist OpenSource!', $translations[1]->getValue());

        // test new import
        $this->import->setFile(__DIR__ . '/../Fixtures/import_better.xliff');
        $this->import->setName('Import Update');
        $this->import->setFormat(Import::XLIFF);
        $this->import->setLocale('de');
        $this->import->setPackageId(1);
        $this->import->execute();

        $package = self::$em->getRepository('SuluTranslateBundle:Package')->find(1);
        $this->assertEquals(1, $package->getId());
        $this->assertEquals('Import Update', $package->getName());

        $catalogue = self::$em->getRepository('SuluTranslateBundle:Catalogue')->find(1);
        $this->assertEquals(1, $catalogue->getId());
        $this->assertEquals('de', $catalogue->getLocale());

        $codes = self::$em->getRepository('SuluTranslateBundle:Code')->findAll();
        $this->assertEquals(1, $codes[0]->getId());
        $this->assertEquals('sulu.great', $codes[0]->getCode());
        $this->assertEquals(true, $codes[0]->getBackend());
        $this->assertEquals(true, $codes[0]->getFrontend());
        $this->assertEquals(null, $codes[0]->getLength());
        $this->assertEquals(2, $codes[1]->getId());
        $this->assertEquals('sulu.open', $codes[1]->getCode());
        $this->assertEquals(true, $codes[1]->getBackend());
        $this->assertEquals(true, $codes[1]->getFrontend());
        $this->assertEquals(null, $codes[1]->getLength());
        $this->assertEquals('sulu.very.great', $codes[2]->getCode());
        $this->assertEquals(true, $codes[2]->getBackend());
        $this->assertEquals(true, $codes[2]->getFrontend());
        $this->assertEquals(null, $codes[2]->getLength());
        $this->assertEquals('sulu.even.open', $codes[3]->getCode());
        $this->assertEquals(true, $codes[3]->getBackend());
        $this->assertEquals(true, $codes[3]->getFrontend());
        $this->assertEquals(null, $codes[3]->getLength());

        $translations = self::$em->getRepository('SuluTranslateBundle:Translation')->findAll();
        $this->assertEquals('Sulu ist wirklich toll!', $translations[0]->getValue());
        $this->assertEquals('Sulu ist OpenSource!', $translations[1]->getValue());
        $this->assertEquals('Sulu ist sehr toll!', $translations[2]->getValue());
        $this->assertEquals('Sulu ist sogar OpenSource!', $translations[3]->getValue());
    }
}

在这里你可以看到导致我问题的功能:

public function execute()
{
    // get correct loader according to format
    $loader = null;
    switch ($this->getFormat()) {
        case self::XLIFF:
            $loader = new XliffFileLoader();
            break;
    }

    $newCatalogue = true;
    if ($this->getPackageId() == null) {
        // create a new package and catalogue for the import
        $package = new Package();
        $catalogue = new Catalogue();
        $catalogue->setPackage($package);
        $this->em->persist($package);
        $this->em->persist($catalogue);
    } else {
        // load the given package and catalogue
        $package = $this->em->getRepository('SuluTranslateBundle:Package')
            ->find($this->getPackageId());

        if (!$package) {
            // If the given package is not existing throw an exception
            throw new PackageNotFoundException($this->getPackageId());
        }

        // find the catalogue from this package matching the given locale
        $catalogue = null;
        foreach ($package->getCatalogues() as $packageCatalogue) {
            /** @var $packageCatalogue Catalogue */
            if ($packageCatalogue->getLocale() == $this->getLocale()) {
                $catalogue = $packageCatalogue;
                $newCatalogue = false;
            }
        }

        // if no catalogue is found create a new one
        if ($newCatalogue) {
            $catalogue = new Catalogue();
            $catalogue->setPackage($package);
            $this->em->persist($catalogue);
        }
    }

    $package->setName($this->getName());
    $catalogue->setLocale($this->getLocale());

    // load the file, and create a new code/translation combination for every message
    $fileCatalogue = $loader->load($this->getFile(), $this->getLocale());
    foreach ($fileCatalogue->all()['messages'] as $key => $message) {
        // Check if code is already existing in current catalogue
        if (!$newCatalogue && ($translate = $catalogue->findTranslation($key))) {
            // Update the old code and translate
            $translate->setValue($message);
        } else {
            // Create new code and translate
            $code = new Code();
            $code->setPackage($package);
            $code->setCode($key);
            $code->setBackend(true);
            $code->setFrontend(true);

            $translate = new Translation();
            $translate->setCode($code);
            $translate->setValue($message);
            $translate->setCatalogue($catalogue);

            $this->em->persist($code);
            $this->em->flush(); //FIXME no flush in between, if possible
            $this->em->persist($translate);
        }
    }

    // save all the changes to the database
    $this->em->flush();
}

问题是我尝试从包中获取目录的行不会返回任何内容。当我调试时,我可以看到包已加载,并且catalogs-property是一个PersistentCollection,它似乎有一个包含元素的ArrayCollection(它还不在_elements-array中)。以下屏幕截图有望更好地解释:

enter image description here

编辑: 我认为问题与缓存机制有关。如果在执行测试之前该行已存在,则读取数据。否则,我已经尝试删除结果缓存,如下面的代码段所示:

public function testXliff()
{
    $cacheDriver = self::$em->getConfiguration()->getResultCacheImpl();

    // test usual import
    $this->import->setFile(__DIR__ . '/../Fixtures/import.xliff');
    $this->import->setName('Import');
    $this->import->setFormat(Import::XLIFF);
    $this->import->setLocale('de');
    $this->import->execute();

    $cacheDriver->deleteAll();

    // test new import
    $this->import->setFile(__DIR__ . '/../Fixtures/import_better.xliff');
    $this->import->setName('Import Update');
    $this->import->setFormat(Import::XLIFF);
    $this->import->setLocale('de');
    $this->import->setPackageId(1);
    $this->import->execute();

    $cacheDriver->deleteAll();

    // test new import with new language code
    $this->import->setFile(__DIR__ . '/../Fixtures/import.xliff');
    $this->import->setName('Import');
    $this->import->setFormat(Import::XLIFF);
    $this->import->setLocale('en');
    $this->import->execute();
}

EDIT2: 我设法让测试运行,但在我看来这只是一个肮脏的解决方法......如果我用$ em-&gt; clear()清除“缓存”,结果是正确的。当然我调试了这个问题,并且意识到使用了EntityManager中identityMap-field的对象,它们已经包含了初始化对象。因此,所有集合都将initialized-flag设置为true,以便不执行延迟加载部分。这是一个错误吗?

0 个答案:

没有答案