Random "Unique violation ERROR" while creating fixtures with faker::uniq
Hi @nikophil, I'm getting random failure from my DB while generating my fixtures and I'm wondering if I'm doing something wrong.
For instance, the last error I got was with the following code
$translationSource1 = TranslationSourceFactory::createOne([
'project' => $project,
]);
TranslationTargetFactory::createOne([
'project' => $project,
'translationSource' => $translationSource1,
]);
TranslationTargetFactory::createOne([
'project' => $project,
'translationSource' => $translationSource1,
]);
which gave me a failure
Doctrine\DBAL\Exception\UniqueConstraintViolationException: An exception occurred while executing a query: SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "languages_pkey"
DETAIL: Key (code)=(code_mr) already exists.
TranslationLabelFactory has
protected function defaults(): array
{
return [
'project' => ProjectFactory::new(),
'translationSource' => TranslationSourceFactory::new(),
'languagePair' => LanguagePairFactory::new(),
];
}
LanguagePairFactory has
protected function defaults(): array
{
return [
'source' => LanguageFactory::new(),
'target' => LanguageFactory::new(),
];
}
and LanguageFactory has
protected function defaults(): array
{
return [
'code' => 'code_'.self::faker()->unique()->languageCode(),
'name' => self::faker()->unique()->text(10),
];
}
By using self::faker()->unique() I expect an unique value every time I create a new fixtures, do I misuse/misunderstand something ?
Edit: also, I feel like the faker instance is shared across all the factories (since it's attached to the Configuration instance), would it be possible to have a faker instance by factory instead ? In my use case I want the value to be unique for a specific factory but two different factories can use the same value.
I dunno if it could help but I'm getting almost every time a random failure since I bumped from 2.7.2 to 2.8.0.
Reverting to 2.7.2 seems to works so it seems like there is some new unwanted behavior...
Edit: This comment might be irrelevant, since bumping again to 2.8.0 seems to work now. Those failure are really random...
Hi @VincentLanglet
any chance you provide a reproducer? even if it does not fail on each test run
This problem could occur if faker()->seed() (or even mt_srand()) is called twice in the same test
any chance you provide a reproducer? even if it does not fail on each test run
Not the easier thing to do since the project is private... I'll see if it really needed.
This problem could occur if
faker()->seed()(or evenmt_srand()) is called twice in the same test
I have the config
when@dev: &dev
# See full configuration: https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#full-default-bundle-configuration
zenstruck_foundry:
enable_auto_refresh_with_lazy_objects: true
persistence:
# Flush only once per call of `PersistentObjectFactory::create()`
flush_once: true
services:
_defaults:
autowire: true
autoconfigure: true
Engine\Tests\Factory\:
resource: '%kernel.project_dir%/tests/Factory/'
when@test: *dev
and in my code I never "manually" touch to faker or mt_srand, my usage feel natural to me
BUT, I just discovered a mistake on my side, while bumping the version I added the code
protected function initialize(): static
{
return $this
->afterPersist(function (Project $project): bool {
if ($project->hasSetting()) {
return false;
}
$project->setSetting(ProjectSettingFactory::createOne(['project' => $this])); // HERE
return true;
});
}
I called ProjectSettingFactory::createOne(['project' => $this]) instead of
ProjectSettingFactory::createOne(['project' => $project]) and it seems that "changing" this solve my issue.
Sorry for the wrong report...
To me it's weird cause:
- it seems that fixtures were created "correctly" without error
- it's not easy to see (to me) the link between this mistake and the error I got
- (Also was hard to debug cause the failure only happen on ci, and I still don't get why I cannot have it locally...)
But maybe you'll see the reason (and if there is something to improve on foundry side to avoid this error or improve the error message ?)