dmaicher / doctrine-test-bundle

Symfony bundle to isolate your app's doctrine database tests and improve the test performance
MIT License
1.08k stars 60 forks source link

[Bug] $entityManager->getReference() results in "Undefined index: 000000004fc9e3630000000009549173" error #157

Closed franzwilding closed 3 years ago

franzwilding commented 3 years ago

Hey!

When using $entityManager->getReference() instead of $entityManager->getRepository()->find() inside a service to get an entity, doctrine will throw an error when using this entity as a reference. This is because the phpunit test have a different instance of the entity manager as the service which results into different sets of cached references (if I understand the problem correctly).

Writing this in my service:

$repo = $this->entityManager->getRepository($class);
$category = $repo->find($id);

$article->setCategory($category);
$this->entityManager->persist($article);
$this->entityManager->flush();

instead of this:

$category = $this->entityManager->getReference($class, $id);

$article->setCategory($category);
$this->entityManager->persist($article);
$this->entityManager->flush();

fixes the problem.

dmaicher commented 3 years ago

Can you explain how this is related to this bundle? This bundle does not deal with the ORM layer of Doctrine at all. It just deals with the DBAL layer and connections.

franzwilding commented 3 years ago

@dmaicher The only thing I know is, that when enabling doctrine-test-bundle, the entityManager instance in my service is not the same as in the test, therefore getReference() will return a different entity instance in the two places which results into the entity reference bug. Disabling the bundle (or just setting enable_static_connection to false) will solve the problem (same entityManager instance in the two places).

dmaicher commented 3 years ago

Ok this is interesting...

Are you able to provide a minimal reproducer project?

dmaicher commented 3 years ago

In case you can provide a reproducer let me know and I can re-open this

jdelaune commented 3 years ago

We have hit a similar issue I believe, after updating to Symfony 5.3 we are now getting a lot of Doctrine\ORM\ORMInvalidArgumentException: A new entity was found through the relationship errors. The ORM seems to think existing entities don't actually exist so is complaining when we try to persist using them. Setting enable_static_connection to false or disabling the bundle also solves the issue for us.

dmaicher commented 3 years ago

Any chance of creating a reproducer?

jdelaune commented 3 years ago

Found our issue in the end, looks like we needed the symfony/proxy-manager-bridge package after upgrading to Symfony 5.3. So probably not related to this thread after all.

carlos-mg89 commented 2 years ago

I'm experiencing the same issue in a ManyToMany relationship.

I'll try to describe the situation as best a possible.

I have a User class with the following ManyToMany relationship:

/**
 * @ORM\ManyToMany(targetEntity=User::class, inversedBy="followedBy")
 * @ORM\JoinTable(name="user_followers")
 */
private $usersFollowed;

/**
 * @ORM\ManyToMany(targetEntity=User::class, mappedBy="usersFollowed")
 */
private $followedBy;

And I'm on Symfony 6.0, Doctrine/DBAL 3.3.6 and doctrine/doctrine-bundle 2.6.3.

And here there are the methods (auto-generated when adding the relationship with bin/console make:entity tool:

/**
     * @return Collection|self[]
     */
    public function getUsersFollowed(): Collection
    {
        return $this->usersFollowed;
    }

    public function addUsersFollowed(self $usersFollowed): self
    {
        if (!$this->usersFollowed->contains($usersFollowed)) {
            $this->usersFollowed[] = $usersFollowed;
        }

        return $this;
    }

    public function removeUsersFollowed(self $usersFollowed): self
    {
        $this->usersFollowed->removeElement($usersFollowed);

        return $this;
    }

    /**
     * @return Collection|self[]
     */
    public function getFollowedBy(): Collection
    {
        return $this->followedBy;
    }

    public function addFollowedBy(self $followedBy): self
    {
        if (!$this->followedBy->contains($followedBy)) {
            $this->followedBy[] = $followedBy;
            $followedBy->addUsersFollowed($this);
        }

        return $this;
    }

    public function removeFollowedBy(self $followedBy): self
    {
        if ($this->followedBy->removeElement($followedBy)) {
            $followedBy->removeUsersFollowed($this);
        }

        return $this;
    }

Other simpler integration tests are working as expected. However, this one is failing:

public function testCountUsersWhoFollowReturnsExpectedCount()
    {
        $userRepository = $this->getUserRepository();
        $followedUser = $this->getNewUser("followed.user@email.com");
        $followerUser = $this->getNewUser("follower.user@email.com");

        $followedUser->addUsersFollowed($followerUser);
        $userRepository->persist($followedUser);
        $count = $userRepository->countUsersWhoFollow($followedUser);

        $this->assertEquals(1, $count);
    }

With the following error:

1) App\Tests\Repository\UserRepositoryIntegrationTest::testCountUsersWhoFollowReturnsExpectedCount
Doctrine\ORM\ORMInvalidArgumentException: A new entity was found through the relationship 'App\Entity\User#usersFollowed' that was not configured to cascade persist operations for entity: follower.user@email.com. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

If I add the ,cascade={"persist"} setting, the test passes, but the code stops working.

I find it quite curious that the code is actually auto generated and is working fine in production and local environments.

I could provide more information.

I've tried by adding the symfony/proxy-manager-bridge package, but the result is the same.

Thank you in advance, and thanks for the great work done on this library. It's really awesome!

dmaicher commented 2 years ago

@carlos-mg89 if you can provide a minimal reproducer repository then I would be happy to look into it

carlos-mg89 commented 2 years ago

Hi again,

It's clearly something unrelated with your library. I've disabled the doctrine-test-bundle, and I'm running only this problematic test, and it's failing anyway. So I need to figure out what's going on.

However, I deeply appreciate your interest, but I don't want to bother you with this matter.