4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\DependencyInjection\Tests\Compiler;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\DependencyInjection\Compiler\FactoryReturnTypePass;
16 use Symfony\Component\DependencyInjection\ContainerBuilder;
17 use Symfony\Component\DependencyInjection\Reference;
18 use Symfony\Component\DependencyInjection\Tests\Fixtures\factoryFunction;
19 use Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryDummy;
20 use Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryParent;
23 * @author Guilhem N. <egetick@gmail.com>
25 class FactoryReturnTypePassTest extends TestCase
27 public function testProcess()
29 $container = new ContainerBuilder();
31 $factory = $container->register('factory');
32 $factory->setFactory(array(FactoryDummy::class, 'createFactory'));
34 $container->setAlias('alias_factory', 'factory');
36 $foo = $container->register('foo');
37 $foo->setFactory(array(new Reference('alias_factory'), 'create'));
39 $bar = $container->register('bar', __CLASS__);
40 $bar->setFactory(array(new Reference('factory'), 'create'));
42 $pass = new FactoryReturnTypePass();
43 $pass->process($container);
45 if (method_exists(\ReflectionMethod::class, 'getReturnType')) {
46 $this->assertEquals(FactoryDummy::class, $factory->getClass());
47 $this->assertEquals(\stdClass::class, $foo->getClass());
49 $this->assertNull($factory->getClass());
50 $this->assertNull($foo->getClass());
52 $this->assertEquals(__CLASS__, $bar->getClass());
56 * @dataProvider returnTypesProvider
58 public function testReturnTypes($factory, $returnType, $hhvmSupport = true)
60 if (!$hhvmSupport && defined('HHVM_VERSION')) {
61 $this->markTestSkipped('Scalar typehints not supported by hhvm.');
64 $container = new ContainerBuilder();
66 $service = $container->register('service');
67 $service->setFactory($factory);
69 $pass = new FactoryReturnTypePass();
70 $pass->process($container);
72 if (method_exists(\ReflectionMethod::class, 'getReturnType')) {
73 $this->assertEquals($returnType, $service->getClass());
75 $this->assertNull($service->getClass());
79 public function returnTypesProvider()
82 // must be loaded before the function as they are in the same file
83 array(array(FactoryDummy::class, 'createBuiltin'), null, false),
84 array(array(FactoryDummy::class, 'createParent'), FactoryParent::class),
85 array(array(FactoryDummy::class, 'createSelf'), FactoryDummy::class),
86 array(factoryFunction::class, FactoryDummy::class),
90 public function testCircularReference()
92 $container = new ContainerBuilder();
94 $factory = $container->register('factory');
95 $factory->setFactory(array(new Reference('factory2'), 'createSelf'));
97 $factory2 = $container->register('factory2');
98 $factory2->setFactory(array(new Reference('factory'), 'create'));
100 $pass = new FactoryReturnTypePass();
101 $pass->process($container);
103 $this->assertNull($factory->getClass());
104 $this->assertNull($factory2->getClass());
107 public function testCompile()
109 $container = new ContainerBuilder();
111 $factory = $container->register('factory');
112 $factory->setFactory(array(FactoryDummy::class, 'createFactory'));
114 if (!method_exists(\ReflectionMethod::class, 'getReturnType')) {
115 if (method_exists($this, 'expectException')) {
116 $this->expectException(\RuntimeException::class);
117 $this->expectExceptionMessage('Please add the class to service "factory" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.');
119 $this->setExpectedException(\RuntimeException::class, 'Please add the class to service "factory" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.');
123 $container->compile();
125 $this->assertEquals(FactoryDummy::class, $container->getDefinition('factory')->getClass());