Skip to content

Behat, foundry and manager registry of the app on different database connection instances #234

@mellowgrab

Description

@mellowgrab

I'm not sure why or how this happens, but it seems that foundry somehow gets different connection instance. I found this while trying to make foundry work with my behat setup, which I'm trying to make to work in database transaction mode, as in my case wiping data from database is not the option (for system to work some huge data package needs to be in the database and importing 0.5gb data on every scenario would make execution time too long).

Some simplified examples how to reproduce:

Feature: Reproduce the bug
  
  Background:
    Given system defaults are loaded
    
  Scenario: Fail
    When mock step
<?php

use Behat\Behat\Context\Context;
use Doctrine\Common\Persistence\ManagerRegistry;

class FeatureContext implements Context
{
    private ManagerRegistry $managerRegistry;

    public function __construct(ManagerRegistry $managerRegistry)
    {
        $this->managerRegistry = $managerRegistry;
    }

    /**
     * @Given /^mock step$/
     */
    public function mockStep()
    {
        return;
    }

    /**
     * @Given /^system defaults are loaded$/
     */
    public function systemDefaultsAreLoaded()
    {
        $manager = $this->managerRegistry->getManager();
        
        /** @var \Doctrine\DBAL\Connection $conn */
        $conn = $manager->getConnection();
        $conn->beginTransaction();

        $foo = \App\Tests\Factory\FooFactory::new()->create();

        $conn->rollback(); // Has no effect, data is already written and commited into database
    }
}

Or:

<?php

use Behat\Behat\Context\Context;
use Doctrine\Common\Persistence\ManagerRegistry;

class FeatureContext implements Context
{
    private ManagerRegistry $managerRegistry;

    public function __construct(ManagerRegistry $managerRegistry)
    {
        $this->managerRegistry = $managerRegistry;
    }

    /**
     * @Given /^mock step$/
     */
    public function mockStep()
    {
        return;
    }

    /**
     * @Given /^system defaults are loaded$/
     */
    public function systemDefaultsAreLoaded()
    {
        $manager = $this->managerRegistry->getManager();
        
        /** @var \Doctrine\DBAL\Connection $conn */
        $conn = $manager->getConnection();
        $conn->beginTransaction();

        $foo = \App\Tests\Factory\FooFactory::new()->withoutPersisting()->create();
        
        $manager->persist($foo->object());
        $manager->flush();
        
        $foosInFoundry = \App\Tests\Factory\FooFactory::repository()->findAll(); // Result - []
        $foosInManager = $manager->getRepository(Foo::class)->findAll(); // Result - [Object Foo::class]
        
        $manager->rollback(); // Rollbacks the Foo insert, which can't be found by repository() method of foundry
    }
}

The suggested lib to have database resets - dama/doctrine-test-bundle would fail in the same fashion and using it would just result in data written into database.

Unfortunately I'm not sure why this happens so can't make MR with solution proposed.

Some additional info:

php: 7.4
mysql: 5.7
symfony: 4.4.36
foundry: 1.15.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions