test(orm): regression — every entity with a custom repo declares repositoryClass

Auto-discovers each mapped entity that has a sibling <Entity>Repository class
and asserts getRepository() returns it (not Doctrine's default). Catches the
prod-only opcache.preload bug class that broke /oauth/userinfo.
This commit is contained in:
hamed
2026-06-28 16:53:40 +03:30
parent 093293004a
commit 372bea4849
@@ -0,0 +1,44 @@
<?php
namespace App\Tests\Doctrine;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
/**
* Regression for the prod-only bug where entities without an explicit
* #[ORM\Entity(repositoryClass: ...)] fell back to Doctrine's default
* repository under opcache.preload, so custom finder methods threw
* BadMethodCallException (e.g. /oauth/userinfo 500).
*
* For every mapped entity that has a sibling <Entity>Repository class
* (App\<Domain>\Entity\X -> App\<Domain>\Repository\XRepository), assert
* getRepository() actually returns that custom class.
*/
class RepositoryClassMappingTest extends KernelTestCase
{
public function testEntitiesWithCustomRepoDeclareIt(): void
{
self::bootKernel();
$em = static::getContainer()->get(EntityManagerInterface::class);
$offenders = [];
foreach ($em->getMetadataFactory()->getAllMetadata() as $meta) {
$entity = $meta->getName();
$repoFqcn = str_replace('\\Entity\\', '\\Repository\\', $entity) . 'Repository';
if (!class_exists($repoFqcn)) {
continue;
}
$actual = $em->getRepository($entity);
if (!$actual instanceof $repoFqcn) {
$offenders[] = sprintf('%s -> got %s, expected %s', $entity, $actual::class, $repoFqcn);
}
}
$this->assertSame(
[],
$offenders,
"Entities missing #[ORM\\Entity(repositoryClass: ...)]:\n" . implode("\n", $offenders),
);
}
}