From b0937fd829c5ab49f0a42d97dbbc152cd2dea9a7 Mon Sep 17 00:00:00 2001 From: vdmorozov Date: Wed, 11 Dec 2024 18:59:03 +0500 Subject: [PATCH 1/2] fix: callback in LazyServiceFactory does not reset initializer in proxy class when building dependency fails Signed-off-by: vdmorozov --- src/Proxy/LazyServiceFactory.php | 2 +- test/Proxy/LazyServiceFactoryTest.php | 32 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Proxy/LazyServiceFactory.php b/src/Proxy/LazyServiceFactory.php index 56ccfe4a..438bbf6a 100644 --- a/src/Proxy/LazyServiceFactory.php +++ b/src/Proxy/LazyServiceFactory.php @@ -42,8 +42,8 @@ public function __invoke( ): VirtualProxyInterface { if (isset($this->servicesMap[$name])) { $initializer = static function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($callback): bool { - $proxy->setProxyInitializer(null); $wrappedInstance = $callback(); + $proxy->setProxyInitializer(null); return true; }; diff --git a/test/Proxy/LazyServiceFactoryTest.php b/test/Proxy/LazyServiceFactoryTest.php index 582f135f..7553285e 100644 --- a/test/Proxy/LazyServiceFactoryTest.php +++ b/test/Proxy/LazyServiceFactoryTest.php @@ -15,6 +15,7 @@ use ProxyManager\Proxy\LazyLoadingInterface; use ProxyManager\Proxy\VirtualProxyInterface; use Psr\Container\ContainerInterface; +use RuntimeException; #[CoversClass(LazyServiceFactory::class)] final class LazyServiceFactoryTest extends TestCase @@ -94,4 +95,35 @@ static function ($className, $initializer) use ($expectedService, $proxy): MockO self::assertSame($expectedService, $result, 'service created not match the expected'); } + + public function testDoesNotResetInitializerWhenCallbackThrowsException(): void + { + $exception = new RuntimeException('Test exception'); + $callback = function () use ($exception): void { + throw $exception; + }; + + $proxy = $this->createMock(LazyLoadingInterface::class); + $proxy + ->expects(self::never()) + ->method('setProxyInitializer'); + + $expectedService = $this->createMock(VirtualProxyInterface::class); + + $this->proxyFactory + ->expects(self::once()) + ->method('createProxy') + ->willReturnCallback( + static function (string $className, callable $initializer) use ($expectedService, $proxy): MockObject { + $wrappedInstance = null; + $initializer($wrappedInstance, $proxy); + return $expectedService; + } + ); + + $this->expectExceptionObject($exception); + $result = $this->factory->__invoke($this->container, 'fooService', $callback); + + self::assertSame($expectedService, $result); + } } From 5722eaadea5375374e44a05678536a2c617e416a Mon Sep 17 00:00:00 2001 From: vdmorozov Date: Wed, 11 Dec 2024 19:07:29 +0500 Subject: [PATCH 2/2] fix: suppress irrelevant psalm inspection in tests Signed-off-by: vdmorozov --- test/Proxy/LazyServiceFactoryTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Proxy/LazyServiceFactoryTest.php b/test/Proxy/LazyServiceFactoryTest.php index 7553285e..19566b2e 100644 --- a/test/Proxy/LazyServiceFactoryTest.php +++ b/test/Proxy/LazyServiceFactoryTest.php @@ -114,6 +114,7 @@ public function testDoesNotResetInitializerWhenCallbackThrowsException(): void ->expects(self::once()) ->method('createProxy') ->willReturnCallback( + /** @psalm-suppress UnusedVariable */ static function (string $className, callable $initializer) use ($expectedService, $proxy): MockObject { $wrappedInstance = null; $initializer($wrappedInstance, $proxy);