diff --git a/src/DependencyInjection/CompilerPass/ProxyServiceWithMockPass.php b/src/DependencyInjection/CompilerPass/ProxyServiceWithMockPass.php index 62bfad1..c69439c 100644 --- a/src/DependencyInjection/CompilerPass/ProxyServiceWithMockPass.php +++ b/src/DependencyInjection/CompilerPass/ProxyServiceWithMockPass.php @@ -42,9 +42,17 @@ public function process(ContainerBuilder $container) }; $proxy = $factory->createProxy($definition->getClass(), $initializer); - $definition->setClass(get_class($proxy)); + $definition->setClass($proxyClass = get_class($proxy)); $definition->setPublic(true); $definition->setLazy(true); + + if (null !== $definition->getFactory()) { + $factoryMethod = $definition->getFactory(); + $arguments = $definition->getArguments(); + array_unshift($arguments, $factoryMethod); + $definition->setFactory([$proxyClass, '__construct_with_factory']); + $definition->setArguments($arguments); + } } } } diff --git a/src/Generator/LazyLoadingValueHolderGenerator.php b/src/Generator/LazyLoadingValueHolderGenerator.php index 9381fd2..bfa081a 100644 --- a/src/Generator/LazyLoadingValueHolderGenerator.php +++ b/src/Generator/LazyLoadingValueHolderGenerator.php @@ -104,6 +104,7 @@ static function (MethodGenerator $generatedMethod) use ($originalClass, $classGe [ new StaticProxyConstructor($initializer, Properties::fromReflectionClass($originalClass)), Constructor::generateMethod($originalClass, $valueHolder), // Not a standard constructor + StaticConstructor::generateMethod($valueHolder), // Not a standard constructor new MagicGet($originalClass, $initializer, $valueHolder, $publicProperties), new MagicSet($originalClass, $initializer, $valueHolder, $publicProperties), new MagicIsset($originalClass, $initializer, $valueHolder, $publicProperties), diff --git a/src/Generator/StaticConstructor.php b/src/Generator/StaticConstructor.php new file mode 100644 index 0000000..825a2e4 --- /dev/null +++ b/src/Generator/StaticConstructor.php @@ -0,0 +1,43 @@ +setStatic(true); + $constructor->setParameter(new ParameterGenerator('factory', 'callable')); + $parameter = new ParameterGenerator('arguments'); + $parameter->setVariadic(true); + $constructor->setParameter($parameter); + + $constructor->setBody( + 'static $reflection;'."\n\n" + .'$reflection = $reflection ?? new \ReflectionClass(self::class);'."\n" + .'$model = $reflection->newInstanceWithoutConstructor();'."\n" + .'$model->'.$valueHolder->getName().' = \Closure::fromCallable($factory)->__invoke(...$arguments);'."\n" + .'\Happyr\ServiceMocking\ServiceMock::initializeProxy($model);'."\n\n" + .'return $model;' + ); + + return $constructor; + } +} diff --git a/tests/Functional/BundleInitializationTest.php b/tests/Functional/BundleInitializationTest.php index 86219b3..3b9d5cd 100644 --- a/tests/Functional/BundleInitializationTest.php +++ b/tests/Functional/BundleInitializationTest.php @@ -7,6 +7,7 @@ use Happyr\ServiceMocking\HappyrServiceMockingBundle; use Happyr\ServiceMocking\ServiceMock; use Happyr\ServiceMocking\Tests\Resource\ExampleService; +use Happyr\ServiceMocking\Tests\Resource\ServiceWithFactory; use Happyr\ServiceMocking\Tests\Resource\StatefulService; use Nyholm\BundleTest\BaseBundleTestCase; use ProxyManager\Proxy\VirtualProxyInterface; @@ -54,6 +55,21 @@ public function testInitBundle() ServiceMock::swap($service, $mock); $this->assertSame(2, $service->getNumber()); + + $serviceWithFactory = $container->get(ServiceWithFactory::class); + $this->assertSame(3, $serviceWithFactory->getSecretNumber()); + + $called = false; + ServiceMock::next($serviceWithFactory, 'getNumber', function ($dir) use (&$called) { + $called = true; + $this->assertSame(11, $dir); + + return 17; + }); + + $this->assertSame(17, $serviceWithFactory->getNumber(11)); + $this->assertTrue($called); + $this->assertSame(14, $serviceWithFactory->getNumber(11)); } public function testRebootBundle() diff --git a/tests/Functional/config.yml b/tests/Functional/config.yml index 9433afc..86edf14 100644 --- a/tests/Functional/config.yml +++ b/tests/Functional/config.yml @@ -1,6 +1,7 @@ happyr_service_mocking: services: - 'Happyr\ServiceMocking\Tests\Resource\ExampleService' + - 'Happyr\ServiceMocking\Tests\Resource\ServiceWithFactory' services: @@ -10,3 +11,7 @@ services: Happyr\ServiceMocking\Tests\Resource\StatefulService: tags: - { name: happyr_service_mock } + + Happyr\ServiceMocking\Tests\Resource\ServiceWithFactory: + factory: [Happyr\ServiceMocking\Tests\Resource\ServiceWithFactory, create] + arguments: [6,3] diff --git a/tests/Resource/ServiceWithFactory.php b/tests/Resource/ServiceWithFactory.php new file mode 100644 index 0000000..913a0b2 --- /dev/null +++ b/tests/Resource/ServiceWithFactory.php @@ -0,0 +1,34 @@ +number = $number; + } + + public static function create(int $number, int $secret) + { + $self = new self($number); + $self->secretNumber = $secret; + + return $self; + } + + public function getNumber(int $input = 0): int + { + return $this->number + $input - $this->secretNumber; + } + + public function getSecretNumber(): int + { + return $this->secretNumber; + } +} diff --git a/tests/Unit/.gitignore b/tests/Unit/.gitignore deleted file mode 100644 index e69de29..0000000