phpsymfonydoctrinefunctional-testingliiptestfixturesbundle

Fixture object reference incorrect in functional test


A functional test class relies on an object reference created in a fixture. The reference's id, however, is not identical to the object's id property as returned by the entity manager. Below is a test that demonstrates this problem.

Notes:

  1. The error is the same when using $this->setReference(...) as when using the public const ... and $this->addReference(...).
  2. The object reference used in the test appears to be the next available id for nonprofit entities.
  3. The test class was created after the error was observed in a more general test class.
  4. The error is the same whether or not the fixtures are loaded before running the test class.
  5. The application uses Symfony 5.1.2 with all dependencies updated.

Test class:

namespace App\Tests\Controller;

use Liip\TestFixturesBundle\Test\FixturesTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class ReferenceTest extends WebTestCase
{

    use FixturesTrait;

    public function setup(): void {
        $this->client = $this->createClient();

        $this->fixtures = $this->loadFixtures([
                    'App\DataFixtures\Test\OptionsFixture',
                    'App\DataFixtures\Test\NonprofitFixture',
                    'App\DataFixtures\Test\OpportunityFixture',
                    'App\DataFixtures\Test\UserFixture',
                ])
                ->getReferenceRepository();
        $this->client->followRedirects();

        $kernel = self::bootKernel();

        $this->entityManager = $kernel->getContainer()
                ->get('doctrine')
                ->getManager('test');
    }

    public function testNonprofitReference() {
        $npo = $this->entityManager->getRepository(\App\Entity\Nonprofit::class)
                ->findOneBy(['orgname' => 'Marmot Fund']);
        $nId = $npo->getId();
        $id = $this->fixtures->getReference('npo')->getId();

        $this->assertEquals($nId, $id, 'Reference incorrect');
    }   
}

Test result:

Reference incorrect
Failed asserting that 4 matches expected 1.

NonprofitFixture (other fixtures may not be relevant):

namespace App\DataFixtures\Test;

use App\Entity\Nonprofit;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Bundle\FixturesBundle\ORMFixtureInterface;

class NonprofitFixture extends AbstractFixture implements OrderedFixtureInterface, ORMFixtureInterface
{

    public const NPO_REFERENCE = 'npo';

    public function load(ObjectManager $manager) {
        $npo = new Nonprofit();
        $npo->setOrgname('Marmot Fund');
        $npo->setEin('123456789');
        $npo->setActive(false);
//        $this->setReference('npo', $npo);
        $this->addReference(self::NPO_REFERENCE, $npo);

        $npo1 = new Nonprofit();
        $npo1->setOrgname('Turkey Fund');
        $npo1->setEin('321654978');
        $npo1->setActive(true);
        $npo1->setWebsite('http://turkeysRUs.bogus.info');

        $npo3 = new Nonprofit();
        $npo3->setOrgname('Talk Trash Fund');
        $npo3->setEin('978654321');
        $npo3->setActive(true);
        $npo3->setWebsite('http://ttrash.bogus.info');

        $staff = $this->getReference(UserFixture::STAFF_REFERENCE);
        $npo->setStaff($staff);
        
        $opp = $this->getReference(OpportunityFixture::OPP_REFERENCE);
        $opp1 = $this->getReference(OpportunityFixture::OPP1_REFERENCE);
        $npo1->addOpportunity($opp);
        $npo3->addOpportunity($opp1);

        $manager->persist($npo);
        $manager->persist($npo1);
        $manager->persist($npo3);

        $manager->flush();
    }

    public function getOrder() {
        return 5; // the order in which fixtures will be loaded
    }

}

framework.yaml excerpt:

liip_test_fixtures:
    keep_database_and_schema: true
    cache_db:
        sqlite: liip_test_fixtures.services_database_backup.sqlite

dama_doctrine_test_bundle.yaml:

dama_doctrine_test:
    enable_static_connection: true
    enable_static_meta_data_cache: true
    enable_static_query_cache: true

csv export from app.db:

"id","orgName"
"1","Marmot Fund"
"2","Turkey Fund"
"3","Talk Trash Fund"

Solution

  • The answer, such as it is, is that references have no place in a functional test. Their use is really a shortcut for clicking on links or taking some other action. A better test is to use the crawler to mimic the action.