使用assertEquals测试Doctrine2实体会导致致命的内存不足错误

时间:2012-03-22 03:28:56

标签: php doctrine-orm phpunit

我有一个使用Doctrine2自定义存储库和Doctrine Fixtures的PHPUnit测试。我想测试一个查询让我从夹具中找回了一个预期的实体。

但是当我尝试$this->assertEquals($expectedEntity, $result);时,我得到Fatal error: out of memory。我猜它正在递归到所有关系和实体管理器等等。

有没有一种好方法来测试这种平等?我应该只断言实体的ID吗?

修改 这是测试代码

<?php
use Liip\FunctionalTestBundle\Test\WebTestCase;

class AbstractRepositoryTestCase extends WebTestCase
{
    /**
     * @var Doctrine\ORM\EntityRepository 
     */
    protected $repo;

    /**
     * @var Doctrine\Common\DataFixtures\Executor\AbstractExecutor
     */
    protected $fixtureExecutor;

    /**
     * @var string Which repository to load, overriden by derived class
     */
    protected $repoName;

    /**
     * @var array Fixture classes to load on setup
     */
    protected $fixtures = array();

    public function setUp()
    {
        $kernel = static::createKernel();
        $this->repo = $kernel->boot();
        $this->repo = $kernel->getContainer()
                             ->get('doctrine.orm.entity_manager')
                             ->getRepository($this->repoName);

        $this->fixtureExecutor = $this->loadFixtures($this->getFixtures());
    }

    public function getFixtures()
    {
        return $this->fixtures;
    }
}

class ArticleRepositoryTest extends AbstractRepositoryTestCase
{
    /**
     * @var string Which repository to load, overriden by derived class
     */
    protected $repoName = 'MyMainBundle:Article';

    /**
     * @var array Fixture classes to load on setup
     */
    protected $fixtures = array(
        'My\MainBundle\DataFixtures\ORM\LoadUserData',
        'My\MainBundle\DataFixtures\ORM\LoadArticleData',
        'My\MainBundle\DataFixtures\ORM\LoadFeedsData',
        'My\MainBundle\DataFixtures\ORM\LoadFeedDataData',
        'My\MainBundle\DataFixtures\ORM\LoadUserReadArticleData',
    );
    public function testGetNextArticle_ExpectCorrect()
    {
        /** @var Doctrine\Common\DataFixtures\ReferenceRepository **/
        $refRepo = $this->fixtureExecutor->getReferenceRepository();

        /** @var FeedStream\MainBundle\Entity\Article **/
        $curr = $refRepo->getReference('feed-1-article-3');
        $expected = $refRepo->getReference('feed-1-article-2');
        $expected2 = $refRepo->getReference('feed-1-article-1');
        $next = $this->repo->getNextArticle($curr->getFeed()->getId(), $curr);

        $this->assertNotNull($next);
        // this is the part that doesn't work
        $this->assertEquals($expected, $next);
        // this is the code I've used instead
        $this->assertEquals($expected->getId(), $next->getId());
    }
}

这是实体(省略了getters / setters以节省空间)

<?php

namespace My\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * My\MainBundle\Entity\Article
 *
 * @ORM\Table(name="articles", uniqueConstraints={
 *   @ORM\UniqueConstraint(name="feed_guid", columns={"feed_id", "guid"}),
 *   @ORM\UniqueConstraint(name="article_slug_unique", columns={"feed_id", "slug"})
 * })
 * @ORM\Entity(repositoryClass="My\MainBundle\Repository\ArticleRepository")
 */
class Article
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string $guid
     *
     * @ORM\Column(name="guid", type="string", length=255, nullable=false)
     */
    private $guid;

    /**
     * @var string $title
     *
     * @ORM\Column(name="title", type="string", length=255, nullable=false)
     */
    private $title;

    /**
     * @var datetime $pubDate
     *
     * @ORM\Column(name="pub_date", type="datetime", nullable=true)
     */
    private $pubDate;

    /**
     * @var text $summary
     *
     * @ORM\Column(name="summary", type="text", nullable=true)
     */
    private $summary;

    /**
     * @var text $content
     *
     * @ORM\Column(name="content", type="text", nullable=false)
     */
    private $content;

    /**
     * @var string $sourceUrl
     *
     * @ORM\Column(name="source_url", type="string", length=255, nullable=true)
     */
    private $sourceUrl;

    /**
     * @var string $commentUrl
     *
     * @ORM\Column(name="comment_url", type="string", length=255, nullable=true)
     */
    private $commentUrl;

    /**
     * @var string $slug
     *
     * @ORM\Column(name="slug", type="string", length=64, nullable=false)
     */
    private $slug;

    /**
     * @var string $thumbnailFile
     *
     * @ORM\Column(name="thumbnail_file", type="string", length=64, nullable=true)
     */
    private $thumbnailFile;

    /**
     * @var My\MainBundle\Entity\ArticleEnclosure
     *
     * @ORM\ManyToOne(targetEntity="My\MainBundle\Entity\ArticleEnclosure")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="thumbnail_enclosure_id", referencedColumnName="id")
     * })
     */
    private $thumbnailEnclosure;

    /**
     * @var My\MainBundle\Entity\ArticleImageScrape
     *
     * @ORM\ManyToOne(targetEntity="My\MainBundle\Entity\ArticleImageScrape")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="thumbnail_scrape_id", referencedColumnName="id", unique=false)
     * })
     */
    private $thumbnailScrape;

    /**
     * @var My\MainBundle\Entity\ArticleBitly
     *
     * @ORM\OneToOne(targetEntity="My\MainBundle\Entity\ArticleBitly", mappedBy="article", orphanRemoval=true)
     */
    private $bitly;

    /**
     * @var My\MainBundle\Entity\ArticleEnclosure
     *
     * @ORM\OneToMany(targetEntity="My\MainBundle\Entity\ArticleEnclosure", mappedBy="article", orphanRemoval=true)
     */
    private $enclosures;

    /**
     * @var My\MainBundle\Entity\ArticleImageScrape
     *
     * @ORM\OneToMany(targetEntity="My\MainBundle\Entity\ArticleImageScrape", mappedBy="article", orphanRemoval=true)
     */
    private $scrapes;

    /**
     * @var My\MainBundle\Entity\ArticleLink
     *
     * @ORM\OneToMany(targetEntity="My\MainBundle\Entity\ArticleLink", mappedBy="article", orphanRemoval=true)
     */
    private $links;

    /**
     * @var My\MainBundle\Entity\Feed
     *
     * @ORM\ManyToOne(targetEntity="My\MainBundle\Entity\Feed", inversedBy="articles")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="feed_id", referencedColumnName="id", nullable=false)
     * })
     */
    private $feed;

    /**
     * @var My\MainBundle\Entity\ArticleAuthor
     *
     * @ORM\ManyToOne(targetEntity="My\MainBundle\Entity\ArticleAuthor", inversedBy="articles")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     * })
     */
    private $author;

    public function __construct()
    {
        $this->links = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

2 个答案:

答案 0 :(得分:3)

如果实体是等于的,assertEquals可以与Doctrine实体一起使用。

当对象不相同时会发生问题,然后phpunit会根据你的图表探索entites图并且永远不会结束。 不幸的是,maxDepth的{​​{1}}参数似乎没有像预期的那样限制递归,所以我担心解决方案是:

  • assertEquals需要保留实体,并在发生故障时提供不匹配对象的标识符

  • $this->assertEquals($entity1->getId(), $entity2->getId())$this->assertEquals(spl_object_hash($entity1), spl_object_hash($entity2))两者都完美有效,但他们并未向您提供有关差异的详细信息

  • 最佳解决方案恕我直言:将实体转换为具有类名称和数组比较属性的数组:

    使用Doctrine \ Common \ Util \ Debug; $ this-&gt; assertEquals(Debug :: export($ entity1),Debug :: export($ entity2));

这会给你一个明确的错误,说明什么属性是不同的(在这种情况下,甚至班级也不同)

$this->assertTrue($entity1 === $entity2)

(您可以将此比较放入Failed asserting that two objects are equal. --- Expected +++ Actual @@ @@ stdClass Object ( - '__CLASS__' => 'Service\Entity\RoleLN' - 'id' => 'ln_admin' - 'isApprover' => false - 'rate' => null - 'name' => 'ln_admin' - 'roles' => null - 'processTasks' => null + '__CLASS__' => 'Service\Entity\Role' + 'id' => 99 + 'rate' => 400 + 'name' => 'roleAdmin' + 'roleLN' => stdClass Object (...) + 'organisation' => stdClass Object (...) + 'users' => null + 'matterRoles' => Array ()

之类的方法中

答案 1 :(得分:0)

除了ID之外,您还应该测试该类。