简体   繁体   English

Symfony Doctrine 关系在 PhpUnit 测试中为空

[英]Symfony Doctrine relationship empty in PhpUnit test

I have a Symfony app with a User entity with a many-to-many relation to a Cat entity.我有一个 Symfony 应用程序,其User实体与Cat实体具有多对多关系。 I also have a PhpUnit test which checks that deleting a cat (that belongs to 2 users) from 1 user doesn't actually delete the cat:我还有一个 PhpUnit 测试,它检查从 1 个用户删除一只猫(属于 2 个用户)实际上并没有删除猫:

    public function testDeletingACatBelongingToTwoUsersOnlyDeletesTheAssociationNotTheCat()
    {
        $cat = $this->createCat();
        // Associate with user 1
        $user1 = new User();
        $user1->setEmail('test@example.com');
        $user1->setPassword('pwdpwd');
        $user1->addCat($cat);
        $this->em->persist($user1);
        // Associate with user 2
        $user2 = new User();
        $user2->setEmail('another@example.com');
        $user2->setPassword('pwdpwd');
        $user2->addCat($cat);
        $this->em->persist($user2);
        $this->em->flush();
        // Sanity check:
        $this->assertCount(1, $user1->getCats()); // PASS
        $this->assertCount(1, $user2->getCats()); // PASS
        $this->assertCount(2, $cat->getUsers()); // FAIL (0)
        // ... perform the test (not shown here)
    }

    private function createCat(): Cat
    {
        $cat = new Cat();
        $cat->setName($this->name);
        $this->em->persist($cat);
        $this->em->flush();

        return $cat;
    }

My question is, why does $cat->getUsers() return 0 in my test?我的问题是,为什么$cat->getUsers()在我的测试中返回0 At runtime it doesn't, it returns the correct value.在运行时它不会,它返回正确的值。 It's only in the test that it returns 0 .它仅在测试中返回0

Here are the relevant excerpts from my entities, auto-generated by Symfony:以下是我的实体的相关摘录,由 Symfony 自动生成:

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */
class User implements UserInterface
{
    /**
     * @ORM\ManyToMany(targetEntity=Cat::class, inversedBy="users")
     */
    private $cats;

    /**
     * @return Collection|Cat[]
     */
    public function getCats(): Collection
    {
        return $this->cats;
    }

    public function addCat(Cat $cat): self
    {
        if (!$this->cats->contains($cat)) {
            $this->cats[] = $cat;
        }

        return $this;
    }

    public function removeCat(Cat $cat): self
    {
        $this->cats->removeElement($cat);

        return $this;
    }
}

/**
 * @ORM\Entity(repositoryClass=CatRepository::class)
 */
class Cat
{
    /**
     * @ORM\ManyToMany(targetEntity=User::class, mappedBy="cats")
     */
    private $users;

    /**
     * @return Collection|User[]
     */
    public function getUsers(): Collection
    {
        return $this->users;
    }
}

The reason is, that collections are not synchronized with the database and synchronization between owning and inverse side is not automatically done either.原因是,collections 没有与数据库同步,拥有方和反向方之间的同步也不会自动完成。

The category entries of your user entity probably will be persisted to the database (although I'm missing some cascade statements, but what do I know).您的用户实体的类别条目可能会保存到数据库中(虽然我缺少一些级联语句,但我知道什么)。 When the category is created, it's collection of users is empty (obviously), then users add the category to the many-to-many relation in database.创建类别时,它的用户集合是空的(显然),然后用户将类别添加到数据库中的多对多关系中。

BUT, the collection is a plain collection.但是,该系列是一个普通的系列。 If you loaded the category from the database, it would be a lazy-loaded PersistentCollection (or something alike), which would - only at the moment of access - fetch the items from the database (definition of lazy loading).如果您从数据库加载类别,它将是一个延迟加载的 PersistentCollection(或类似的东西),它只会在访问时从数据库中获取项目(延迟加载的定义)。 Your test code has the plain collection (since you created the object yourself).您的测试代码具有普通集合(因为您自己创建了 object)。

Not quite sure, if it'll work, but you could try refreshing the cat ( $em->refresh($cat); ) I'm not quite certain though, if that will replace the collection.不太确定,如果它会工作,但你可以尝试刷新猫( $em->refresh($cat); )我不太确定,如果它会替换集合。 Alternatively, you could make your User::addCat that it also calls $cat->addUser($this) (which you might have to add, beware the infinite recursion, which already should be prevented by the "contains" checks.).或者,您可以让您的User::addCat也调用$cat->addUser($this) (您可能必须添加它,注意无限递归,“包含”检查已经应该阻止它。)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM