diff --git a/src/Proxy/LazyServiceFactory.php b/src/Proxy/LazyServiceFactory.php index 56ccfe4a..79170e31 100644 --- a/src/Proxy/LazyServiceFactory.php +++ b/src/Proxy/LazyServiceFactory.php @@ -11,6 +11,7 @@ use ProxyManager\Proxy\VirtualProxyInterface; use Psr\Container\ContainerInterface; +use Throwable; use function sprintf; /** @@ -42,8 +43,14 @@ public function __invoke( ): VirtualProxyInterface { if (isset($this->servicesMap[$name])) { $initializer = static function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($callback): bool { + $initializer = $proxy->getProxyInitializer(); $proxy->setProxyInitializer(null); - $wrappedInstance = $callback(); + try { + $wrappedInstance = $callback(); + } catch (Throwable $e) { + $proxy->setProxyInitializer($initializer); + throw $e; + } return true; }; diff --git a/test/Proxy/LazyServiceFactoryTest.php b/test/Proxy/LazyServiceFactoryTest.php index 582f135f..fc7d80f6 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,51 @@ static function ($className, $initializer) use ($expectedService, $proxy): MockO self::assertSame($expectedService, $result, 'service created not match the expected'); } + + public function testHandlesExceptionInInitializer(): void + { + $exception = new RuntimeException('Test exception'); + $callback = fn() => throw $exception; + + $proxy = $this->createMock(LazyLoadingInterface::class); + $initializer = fn() => true; + + $proxy->expects(self::once()) + ->method('getProxyInitializer') + ->willReturn($initializer); + + $proxy + ->expects(self::exactly(2)) + ->method('setProxyInitializer') + ->willReturnMap( + [ + [null], + [$initializer], + ] + ); + + $expectedService = $this->createMock(VirtualProxyInterface::class); + + $this->proxyFactory + ->expects(self::once()) + ->method('createProxy') + ->willReturnCallback( + static function ($className, $initializer) use ($expectedService, $proxy): MockObject { + self::assertEquals('FooClass', $className); + + $wrappedInstance = null; + + try { + $initializer($wrappedInstance, $proxy); + self::fail('Expected exception was not thrown'); + } catch (RuntimeException) { + } + + return $expectedService; + } + ); + + $result = $this->factory->__invoke($this->container, 'fooService', $callback); + self::assertSame($expectedService, $result); + } }