From 5c2a3d89bef9242ff5228a1ed69a15f9d7622ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Wed, 20 Dec 2023 00:07:17 +0100 Subject: [PATCH 1/3] Backport tests for strict return types (#463) --- tests/Common/DataFixtures/Executor/ORMExecutorTest.php | 6 ++---- tests/Common/DataFixtures/ReferenceRepositoryTest.php | 4 ++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/Common/DataFixtures/Executor/ORMExecutorTest.php b/tests/Common/DataFixtures/Executor/ORMExecutorTest.php index e1ee3961..3df210be 100644 --- a/tests/Common/DataFixtures/Executor/ORMExecutorTest.php +++ b/tests/Common/DataFixtures/Executor/ORMExecutorTest.php @@ -52,8 +52,7 @@ public function testExecuteWithPurge(): void $em = $this->getMockSqliteEntityManager(); $purger = $this->getMockPurger(); $purger->expects($this->once()) - ->method('purge') - ->willReturn(null); + ->method('purge'); $executor = new ORMExecutor($em, $purger); $fixture = $this->getMockFixture(); $fixture->expects($this->once()) @@ -103,8 +102,7 @@ public function testExecuteMultipleTransactionsWithPurge(): void $em = $this->getMockSqliteEntityManager(); $purger = $this->getMockPurger(); $purger->expects($this->once()) - ->method('purge') - ->willReturn(null); + ->method('purge'); $executor = new MultipleTransactionORMExecutor($em, $purger); $fixture = $this->getMockFixture(); $fixture->expects($this->once()) diff --git a/tests/Common/DataFixtures/ReferenceRepositoryTest.php b/tests/Common/DataFixtures/ReferenceRepositoryTest.php index 95b66de5..0472ce08 100644 --- a/tests/Common/DataFixtures/ReferenceRepositoryTest.php +++ b/tests/Common/DataFixtures/ReferenceRepositoryTest.php @@ -199,6 +199,10 @@ public function testGetIdentifierWhenHasNotBeenManagedYetByUnitOfWork(): void ->with($role) ->willReturn($identitiesExpected); + $classMetadata->expects($this->once()) + ->method('getName') + ->willReturn(Role::class); + $em = $this->createMock(ForwardCompatibleEntityManager::class); $em->method('getUnitOfWork') ->willReturn($uow); From d8cfe54f17ee70eccbd3cebb357951e2d9f72a6a Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Fri, 8 Mar 2024 08:16:21 +0100 Subject: [PATCH 2/3] Add tests (#465) --- .../Executor/ORMExecutorSharedFixtureTest.php | 31 ++++++++ .../ProxyReferenceRepositoryTest.php | 35 ++++++++-- .../DataFixtures/ReferenceRepositoryTest.php | 70 ++++++++++++++++--- .../DataFixtures/TestFixtures/UserFixture.php | 3 +- 4 files changed, 122 insertions(+), 17 deletions(-) diff --git a/tests/Common/DataFixtures/Executor/ORMExecutorSharedFixtureTest.php b/tests/Common/DataFixtures/Executor/ORMExecutorSharedFixtureTest.php index f4275f3e..1553e05c 100644 --- a/tests/Common/DataFixtures/Executor/ORMExecutorSharedFixtureTest.php +++ b/tests/Common/DataFixtures/Executor/ORMExecutorSharedFixtureTest.php @@ -56,6 +56,37 @@ public function testSharedFixtures(): void $roleFixture = new TestFixtures\RoleFixture(); $executor->execute([$roleFixture, $userFixture], true); + $referenceRepository = $executor->getReferenceRepository(); + $references = $referenceRepository->getReferencesByClass(); + + $this->assertCount(2, $references); + $roleReference = $referenceRepository->getReference('admin-role', Role::class); + $this->assertInstanceOf(Role::class, $roleReference); + $this->assertEquals('admin', $roleReference->getName()); + + $userReference = $referenceRepository->getReference('admin', User::class); + $this->assertInstanceOf(User::class, $userReference); + $this->assertEquals('admin@example.com', $userReference->getEmail()); + } + + /** @group legacy */ + public function testLegacySharedFixtures(): void + { + $em = $this->getMockSqliteEntityManager(); + $schemaTool = new SchemaTool($em); + $schemaTool->dropSchema([]); + $schemaTool->createSchema([ + $em->getClassMetadata(self::TEST_ENTITY_ROLE), + $em->getClassMetadata(self::TEST_ENTITY_USER), + ]); + + $purger = new ORMPurger(); + $executor = new ORMExecutor($em, $purger); + + $userFixture = new TestFixtures\UserFixture(); + $roleFixture = new TestFixtures\RoleFixture(); + $executor->execute([$roleFixture, $userFixture], true); + $referenceRepository = $executor->getReferenceRepository(); $references = $referenceRepository->getReferences(); diff --git a/tests/Common/DataFixtures/ProxyReferenceRepositoryTest.php b/tests/Common/DataFixtures/ProxyReferenceRepositoryTest.php index 75bf6f07..a4ae20bf 100644 --- a/tests/Common/DataFixtures/ProxyReferenceRepositoryTest.php +++ b/tests/Common/DataFixtures/ProxyReferenceRepositoryTest.php @@ -44,6 +44,27 @@ public function testReferenceEntry(): void $referenceRepo = new ProxyReferenceRepository($em); $referenceRepo->addReference('test', $role); + $referencesByClass = $referenceRepo->getReferencesByClass(); + + $this->assertCount(1, $referencesByClass); + $this->assertArrayHasKey(Role::class, $referencesByClass); + $this->assertCount(1, $referencesByClass[Role::class]); + $this->assertArrayHasKey('test', $referencesByClass[Role::class]); + $this->assertInstanceOf(self::TEST_ENTITY_ROLE, $referencesByClass[Role::class]['test']); + } + + /** @group legacy */ + public function testLegacyReferenceEntry(): void + { + $em = $this->getMockSqliteEntityManager(); + $role = new TestEntity\Role(); + $role->setName('admin'); + $meta = $em->getClassMetadata(self::TEST_ENTITY_ROLE); + $meta->getReflectionProperty('id')->setValue($role, 1); + + $referenceRepo = new ProxyReferenceRepository($em); + $referenceRepo->addReference('test', $role); + $references = $referenceRepo->getReferences(); $this->assertCount(1, $references); @@ -96,7 +117,7 @@ public function testReferenceReconstruction(): void $roleFixture->load($em); // first test against managed state - $ref = $referenceRepository->getReference('admin-role'); + $ref = $referenceRepository->getReference('admin-role', Role::class); $this->assertNotInstanceOf(Proxy::class, $ref); @@ -106,7 +127,7 @@ public function testReferenceReconstruction(): void $proxyReferenceRepository = new ProxyReferenceRepository($em); $proxyReferenceRepository->unserialize($serializedData); - $ref = $proxyReferenceRepository->getReference('admin-role'); + $ref = $proxyReferenceRepository->getReference('admin-role', Role::class); // before clearing, the reference is not yet a proxy $this->assertNotInstanceOf(Proxy::class, $ref); @@ -114,7 +135,7 @@ public function testReferenceReconstruction(): void // now test reference reconstruction from identity $em->clear(); - $ref = $referenceRepository->getReference('admin-role'); + $ref = $referenceRepository->getReference('admin-role', Role::class); $this->assertInstanceOf(Proxy::class, $ref); @@ -124,7 +145,7 @@ public function testReferenceReconstruction(): void $proxyReferenceRepository = new ProxyReferenceRepository($em); $proxyReferenceRepository->unserialize($serializedData); - $ref = $proxyReferenceRepository->getReference('admin-role'); + $ref = $proxyReferenceRepository->getReference('admin-role', Role::class); $this->assertInstanceOf(Proxy::class, $ref); } @@ -154,7 +175,7 @@ public function testReconstructionOfCustomTypedId(): void $this->assertInstanceOf( 'Doctrine\Tests\Common\DataFixtures\TestValueObjects\Uuid', - $proxyReferenceRepository->getReference('home-link')->getId(), + $proxyReferenceRepository->getReference('home-link', Link::class)->getId(), ); } @@ -175,7 +196,7 @@ public function testReferenceMultipleEntries(): void $em->flush(); $em->clear(); - $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('admin')); - $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('duplicate')); + $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('admin', Role::class)); + $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('duplicate', Role::class)); } } diff --git a/tests/Common/DataFixtures/ReferenceRepositoryTest.php b/tests/Common/DataFixtures/ReferenceRepositoryTest.php index 0472ce08..95652a70 100644 --- a/tests/Common/DataFixtures/ReferenceRepositoryTest.php +++ b/tests/Common/DataFixtures/ReferenceRepositoryTest.php @@ -15,6 +15,8 @@ use Doctrine\Tests\Mock\ForwardCompatibleEntityManager; use OutOfBoundsException; +use function sprintf; + class ReferenceRepositoryTest extends BaseTestCase { public function testReferenceEntry(): void @@ -32,6 +34,30 @@ public function testReferenceEntry(): void $referenceRepo->addReference('test', $role); + $referencesByClass = $referenceRepo->getReferencesByClass(); + $this->assertCount(1, $referencesByClass); + $this->assertArrayHasKey(Role::class, $referencesByClass); + $this->assertCount(1, $referencesByClass[Role::class]); + $this->assertArrayHasKey('test', $referencesByClass[Role::class]); + $this->assertInstanceOf(Role::class, $referencesByClass[Role::class]['test']); + } + + /** @group legacy */ + public function testLegacyReferenceEntry(): void + { + $em = $this->getMockSqliteEntityManager(); + + $role = new TestEntity\Role(); + $role->setName('admin'); + + $meta = $em->getClassMetadata(Role::class); + $meta->getReflectionProperty('id')->setValue($role, 1); + + $referenceRepo = new ReferenceRepository($em); + $this->assertSame($em, $referenceRepo->getManager()); + + $referenceRepo->addReference('test', $role); + $references = $referenceRepo->getReferences(); $this->assertCount(1, $references); $this->assertArrayHasKey('test', $references); @@ -57,7 +83,7 @@ public function testReferenceIdentityPopulation(): void $referenceRepository->expects($this->once()) ->method('getReferenceNames') - ->will($this->returnValue(['admin-role'])); + ->willReturn(['admin-role']); $referenceRepository->expects($this->once()) ->method('setReferenceIdentity') @@ -84,13 +110,13 @@ public function testReferenceReconstruction(): void $roleFixture->load($em); // first test against managed state - $ref = $referenceRepository->getReference('admin-role'); + $ref = $referenceRepository->getReference('admin-role', Role::class); $this->assertNotInstanceOf(Proxy::class, $ref); // now test reference reconstruction from identity $em->clear(); - $ref = $referenceRepository->getReference('admin-role'); + $ref = $referenceRepository->getReference('admin-role', Role::class); $this->assertInstanceOf(Proxy::class, $ref); } @@ -112,14 +138,25 @@ public function testReferenceMultipleEntries(): void $em->flush(); $em->clear(); - $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('admin')); - $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('duplicate')); + $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('admin', Role::class)); + $this->assertInstanceOf(Proxy::class, $referenceRepository->getReference('duplicate', Role::class)); } public function testUndefinedReference(): void { $referenceRepository = new ReferenceRepository($this->getMockSqliteEntityManager()); + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage(sprintf('Reference to "foo" for class "%s" does not exist', Role::class)); + + $referenceRepository->getReference('foo', Role::class); + } + + /** @group legacy */ + public function testLegacyUndefinedReference(): void + { + $referenceRepository = new ReferenceRepository($this->getMockSqliteEntityManager()); + $this->expectException(OutOfBoundsException::class); $this->expectExceptionMessage('Reference to "foo" does not exist'); @@ -146,12 +183,24 @@ public function testThrowsExceptionTryingToGetWrongReference(): void $referenceRepository = new ReferenceRepository($this->getMockSqliteEntityManager()); $this->expectException(OutOfBoundsException::class); - $this->expectExceptionMessage('Reference to "missing_reference" does not exist'); + $this->expectExceptionMessage(sprintf('Reference to "missing_reference" for class "%s" does not exist', Role::class)); - $referenceRepository->getReference('missing_reference'); + $referenceRepository->getReference('missing_reference', Role::class); } public function testHasIdentityCheck(): void + { + $role = new Role(); + $referenceRepository = new ReferenceRepository($this->getMockSqliteEntityManager()); + $referenceRepository->setReferenceIdentity('entity', 1, Role::class); + + $this->assertTrue($referenceRepository->hasIdentity('entity', Role::class)); + $this->assertFalse($referenceRepository->hasIdentity('invalid_entity', Role::class)); + $this->assertEquals(['entity' => 1], $referenceRepository->getIdentitiesByClass()[Role::class] ?? []); + } + + /** @group legacy */ + public function testLegacyHasIdentityCheck(): void { $role = new Role(); $referenceRepository = new ReferenceRepository($this->getMockSqliteEntityManager()); @@ -177,7 +226,7 @@ public function testSetReferenceHavingIdentifier(): void $em->flush(); $referenceRepository->setReference('entity', $role); - $identities = $referenceRepository->getIdentities(); + $identities = $referenceRepository->getIdentitiesByClass()[Role::class] ?? []; $this->assertCount(1, $identities); $this->assertArrayHasKey('entity', $identities); } @@ -198,6 +247,9 @@ public function testGetIdentifierWhenHasNotBeenManagedYetByUnitOfWork(): void ->method('getIdentifierValues') ->with($role) ->willReturn($identitiesExpected); + $classMetadata->expects($this->once()) + ->method('getName') + ->willReturn(Role::class); $classMetadata->expects($this->once()) ->method('getName') @@ -212,7 +264,7 @@ public function testGetIdentifierWhenHasNotBeenManagedYetByUnitOfWork(): void $referenceRepository = new ReferenceRepository($em); $referenceRepository->setReference('entity', $role); - $identities = $referenceRepository->getIdentities(); + $identities = $referenceRepository->getIdentitiesByClass()[Role::class] ?? []; $this->assertEquals($identitiesExpected, $identities['entity']); } diff --git a/tests/Common/DataFixtures/TestFixtures/UserFixture.php b/tests/Common/DataFixtures/TestFixtures/UserFixture.php index 383150ff..972b9a01 100644 --- a/tests/Common/DataFixtures/TestFixtures/UserFixture.php +++ b/tests/Common/DataFixtures/TestFixtures/UserFixture.php @@ -6,6 +6,7 @@ use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Persistence\ObjectManager; +use Doctrine\Tests\Common\DataFixtures\TestEntity\Role; use Doctrine\Tests\Common\DataFixtures\TestEntity\User; class UserFixture extends AbstractFixture @@ -17,7 +18,7 @@ public function load(ObjectManager $manager): void $admin->setCode('007'); $admin->setEmail('admin@example.com'); $admin->setPassword('secret'); - $role = $this->getReference('admin-role'); + $role = $this->getReference('admin-role', Role::class); $admin->setRole($role); $manager->persist($admin); From 7a3052e90c736aed321d0d15988fb3650de1145b Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Fri, 8 Mar 2024 08:27:12 +0100 Subject: [PATCH 3/3] Adjust PHPStan settings for ORM 3 (#467) --- phpstan.neon.dist | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 088bd6d0..20b0dc06 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -4,10 +4,14 @@ parameters: paths: - src - tests + excludePaths: + - tests/Mock/ForwardCompatibleEntityManager.php ignoreErrors: - # ORM 3 forward compatibility - - '~^Parameter \$assoc of method Doctrine\\Common\\DataFixtures\\Purger\\ORMPurger\:\:getJoinTableName\(\) has invalid type Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\.$~' + # ORM 2 backwards compatibility + - + message: '#^Call to an undefined static method Doctrine\\ORM\\ORMSetup\:\:createAnnotationMetadataConfiguration\(\)\.$#' + path: tests/Common/DataFixtures/BaseTestCase.php includes: - phpstan-baseline.neon