Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Doctrine] ManyToMany Relationships not persisted in database with haveInRepository nested entity creation #16

Open
Pryrios opened this issue Dec 13, 2019 · 7 comments

Comments

@Pryrios
Copy link

Pryrios commented Dec 13, 2019

What are you trying to achieve?

I am running a functional test on a Symfony 4 + Doctrine 2 with two entities with a ManyToMany relationship. I create the entities using haveInRepository nested functionality and I expect to have the two entities created on the database and related on the join table.

What do you get instead?

The entities are created but relationships in join tables are not, so the test fails due to missing information on database.

Provide console output if related. Use -vvv mode for more details.

vagrant@symfonyvm:/var/www/mtm$ php vendor/bin/codecept run
Codeception PHP Testing Framework v3.1.2
Powered by PHPUnit 8.5.0 by Sebastian Bergmann and contributors.
Running with seed: 


App\Tests.acceptance Tests (0) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

App\Tests.functional Tests (1) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Testing App\Tests.functional
✖ ManytoManyEntitiesCest: Try to test (0.07s)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

App\Tests.unit Tests (0) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Time: 326 ms, Memory: 28.25 MB

There was 1 failure:

---------
1) ManytoManyEntitiesCest: Try to test
 Test  tests/functional/ManytoManyEntitiesCest.php:tryToTest
 Step  See in repository "App\Entity\EntityA",{"entityB":{"name":"Name B"}}
 Fail  App\Entity\EntityA with {"entityB":{"name":"Name B"}}
Failed asserting that false is true.

Scenario Steps:

 4. $I->seeInRepository("App\Entity\EntityA",{"entityB":{"name":"Name B"}}) at tests/functional/ManytoManyEntitiesCest.php:24
 3. $I->seeInRepository("App\Entity\EntityA",{"name":"Name A"}) at tests/functional/ManytoManyEntitiesCest.php:23
 2. $I->seeInRepository("App\Entity\EntityB",{"name":"Name B"}) at tests/functional/ManytoManyEntitiesCest.php:22
 1. $I->haveInRepository("App\Entity\EntityA",{"name":"Name A","entityB":[{"name":"Name B"}]}) at tests/functional/ManytoManyEntitiesCest.php:19


FAILURES!
Tests: 1, Assertions: 3, Failures: 1.

Provide test source code if related

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\EntityARepository")
 */
class EntityA
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\EntityB", inversedBy="entityA")
     */
    private $entityB;
}
<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\EntityBRepository")
 */
class EntityB
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\EntityA", mappedBy="entityB")
     */
    private $entityA;
}
public function cannotSeeManyToManyRelationships(FunctionalTester $I)
{
    $I->haveInRepository(
        EntityA::class,
        [
            'name' => 'Name A',
            'entityB' =>[[ 'name' => 'Name B' ]],
        ]);
    $I->seeInRepository(EntityB::class, ['name' => 'Name B']);
    $I->seeInRepository(EntityA::class, ['name' => 'Name A']);
    $I->seeInRepository(EntityA::class, ['entityB' => ['name' => 'Name B']]);
}

Details

With that setup, the two first seeInRepository pass but the third does not. It could be due to the syntax of the array not being correct on the last assertion as it should really be an array, but if you look into the database you can see that the join table has not been filled.

It may be due a syntax problem, but in that case it should be an issue with docs as it doesn't specify how to work with ManyToMany relationships.

I have created a complete example in this repo: https://github.com/Pryrios/test-manytomany

  • Codeception version: Codeception PHP Testing Framework v3.1.2
  • PHP Version: 7.2
  • Operating System: Ubuntu 18.04
  • Installation type: Composer

functional.suite.yml

actor: FunctionalTester
modules:
    enabled:
        - Symfony:
            app_path: 'src'
            environment: 'test'
        - Doctrine2:
           depends: Symfony
           cleanup: true
        - \App\Tests\Helper\Functional
@Pryrios
Copy link
Author

Pryrios commented Dec 13, 2019

Update: If I create the entities manually instead of using haveInRepository the test passes, so it seems the syntax of the last assertion is correct.

@markopaden
Copy link

I can confirm, I have tried to write a test for API call where I have ManyToMany relation, and I did not receive expected relation in response.

@Naktibalda Naktibalda transferred this issue from Codeception/Codeception Jan 3, 2021
@nnikolay
Copy link

@Pryrios can you post the example how you created the entities manually? I am trying but after I call $em->persist(class), then it fails.

@Pryrios
Copy link
Author

Pryrios commented May 11, 2021

I just created each of the two entities, persisted and flushed the entityManager. Something like:

$entityB = new EntityB("Name B");
$em->persist($entityB);
$entityA = new EntityA("Name A", $entityB);
$em->persist($entityA);
$em->flush();

Please bear in mind that I tested this more than one year ago and I don't remember how I did it manually, this is just what comes to mind.

That would save the entities to the database as well as their relationship which was the missing bit. I dunno why it fails to you. Maybe you are persisting the parent entity but the child one isn't getting persisted?

@bartdens
Copy link

Is there any chance this can be fixed? I (and assume a lot of others) have lost quite a bit of time on this before I realised it was a bug in the module...

@Naktibalda
Copy link
Member

If you know how to fix it, please raise pull request.

@SylvainBreton
Copy link

SylvainBreton commented Sep 4, 2023

I have a similar issue on my project. Functional tests were running fine until I updated libraries (symfony 6.2 -> 6.3) caused this issue.
After some investigation we ended up thinking there may be 2 entityManager in the test.

@TavoNiievez TavoNiievez transferred this issue from Codeception/module-doctrine2 Feb 17, 2024
TavoNiievez pushed a commit that referenced this issue Feb 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants