我写了一个非常复杂的类,我想测试一些功能方面。
因此我使用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中)。以下屏幕截图有望更好地解释:
编辑: 我认为问题与缓存机制有关。如果在执行测试之前该行已存在,则读取数据。否则,我已经尝试删除结果缓存,如下面的代码段所示:
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,以便不执行延迟加载部分。这是一个错误吗?