Question - Using RefreshDatabaseTrait and ReloadDatabaseTrait in Symfony test
Hi,
I'm using this bundle (version 2.15.1) for my symfony tests.
I try to reload the DB before each test using RefreshDatabaseTrait/ReloadDatabaseTrait.
I face some issues :
- When I use ReloadDatabaseTrait, the db is reloaded before each subtest but the the generated ids don't reset.
- When I use RefreshDatabaseTrait, the ids reset (go back to 1 for the first) but the data of each previous subtest are kept. So I think that the database is not refreshed at all and the ids (of the fixtures) are the one from the first subtest.
- When I use RecreateDatabaseTrait, it's working fine but may create some perfomance issues...
namespace App\Tests\Controller;
use App\Entity\Bpu;
use Doctrine\ORM\Exception\ORMException;
use Doctrine\ORM\OptimisticLockException;
use Hautelook\AliceBundle\PhpUnit\FixtureStore;
use Hautelook\AliceBundle\PhpUnit\RefreshDatabaseTrait;
use Liip\FunctionalTestBundle\Test\WebTestCase;
class BpuControllerTest extends WebTestCase
{
use RefreshDatabaseTrait;
use SceneTrait;
private string $path = '/bpu/';
public function testIndex(): void
{
$this->needLogin($this->path);
$this->loginAsAdmin();
$crawler = $this->get($this->path);
self::assertResponseStatusCodeSame(200);
self::assertPageTitleSame('BPU');
}
/**
* @throws \Exception
*/
public function testNew(): void
{
$this->needLogin(sprintf('%snew', $this->path));
$this->loginAsAdmin();
$this->get(sprintf('%snew', $this->path));
self::assertResponseStatusCodeSame(200);
$repository = $this->getEntityManager()->getRepository(Bpu::class);
$nombreArticle = $repository->count([]);
$fixtures = FixtureStore::getFixtures();
$marche1 = $fixtures['marche_1'];
$marche2 = $fixtures['marche_2'];
$this->client->submitForm('Enregistrer', [
'bpu[code]' => 'Code bpu',
'bpu[libelle]' => 'Libelle bpu',
'bpu[actif]' => true,
'bpu[marches]['.$marche1->getId() - 1 .']' => $marche1->getId(),
'bpu[marches]['.$marche2->getId() - 1 .']' => $marche2->getId(),
]);
self::assertResponseStatusCodeSame(303);
self::assertSame($nombreArticle + 1, $repository->count([]));
}
/**
* @throws OptimisticLockException
* @throws ORMException
* @throws \Exception
*/
public function testShow(): void
{
$fixtures = FixtureStore::getFixtures();
$marche1 = $fixtures['marche_1'];
$bpu = new Bpu();
$bpu->setCode('Code BPU');
$bpu->setLibelle('Libelle BPU');
$bpu->setType('TRAVAUX_EP');
$bpu->setActif(1);
$bpu->addMarche($marche1);
$this->getEntityManager()->persist($bpu);
$this->getEntityManager()->flush();
$this->needLogin(sprintf('%s%s', $this->path, $bpu->getId()));
$this->loginAsAdmin();
$this->get(sprintf('%s%s', $this->path, $bpu->getId()));
self::assertResponseStatusCodeSame(200);
self::assertPageTitleSame('Détails BPU');
$repository = $this->getEntityManager()->getRepository(Bpu::class);
$fixture = $repository->find($bpu->getId());
self::assertSame('Code BPU', $fixture->getCode());
self::assertSame('Libelle BPU', $fixture->getLibelle());
self::assertSame('TRAVAUX_EP', $fixture->getType());
self::assertTrue($fixture->isActif());
self::assertSame($marche1->getLibelle(), $fixture->getMarches()[0]->getLibelle());
}
I'm might be doing something wrong or forgetting something.
Thank you !
When I use ReloadDatabaseTrait, the db is reloaded before each subtest but the the generated ids don't reset.
Correct, by design it does a truncate, which does not reset.
When I use RefreshDatabaseTrait, the ids reset (go back to 1 for the first) but the data of each previous subtest are kept. So I think that the database is not refreshed at all and the ids (of the fixtures) are the one from the first subtest.
With it the fixtures are loaded first and then a transaction is started: https://github.com/theofidry/AliceBundle/blob/master/src/PhpUnit/RefreshDatabaseTrait.php#L46
So it kind of depends of what you're doing really. But why would the idea itself changing be an issue? I think if you rely on an auto-generated ID, you need a way to retrieve your specific entity by something else, e.g. a label. Otherwise IMO having auto-generated ID is not recommended and you should use a UUID for instance.
Thank you for the answer !
I changed my way of testing where I had issues so ReloadDatabaseTrait is perfect now.
For the RefreshDatabaseTrait, it seems that the transaction doesn't go back to it's original state after each test or maybe I misunderstand something.
Nevertheless, ReloadDatabaseTrait seems appropriate for my use.
Thanks again