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\HttpKernel\Tests\Controller;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
16 use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
17 use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
18 use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
19 use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
20 use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
21 use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
22 use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest;
23 use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController;
24 use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController;
25 use Symfony\Component\HttpFoundation\Request;
27 class ArgumentResolverTest extends TestCase
29 /** @var ArgumentResolver */
30 private static $resolver;
32 public static function setUpBeforeClass()
34 $factory = new ArgumentMetadataFactory();
35 $argumentValueResolvers = array(
36 new RequestAttributeValueResolver(),
37 new RequestValueResolver(),
38 new DefaultValueResolver(),
39 new VariadicValueResolver(),
42 self::$resolver = new ArgumentResolver($factory, $argumentValueResolvers);
45 public function testDefaultState()
47 $this->assertEquals(self::$resolver, new ArgumentResolver());
48 $this->assertNotEquals(self::$resolver, new ArgumentResolver(null, array(new RequestAttributeValueResolver())));
51 public function testGetArguments()
53 $request = Request::create('/');
54 $request->attributes->set('foo', 'foo');
55 $controller = array(new self(), 'controllerWithFoo');
57 $this->assertEquals(array('foo'), self::$resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method');
60 public function testGetArgumentsReturnsEmptyArrayWhenNoArguments()
62 $request = Request::create('/');
63 $controller = array(new self(), 'controllerWithoutArguments');
65 $this->assertEquals(array(), self::$resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments');
68 public function testGetArgumentsUsesDefaultValue()
70 $request = Request::create('/');
71 $request->attributes->set('foo', 'foo');
72 $controller = array(new self(), 'controllerWithFooAndDefaultBar');
74 $this->assertEquals(array('foo', null), self::$resolver->getArguments($request, $controller), '->getArguments() uses default values if present');
77 public function testGetArgumentsOverrideDefaultValueByRequestAttribute()
79 $request = Request::create('/');
80 $request->attributes->set('foo', 'foo');
81 $request->attributes->set('bar', 'bar');
82 $controller = array(new self(), 'controllerWithFooAndDefaultBar');
84 $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes');
87 public function testGetArgumentsFromClosure()
89 $request = Request::create('/');
90 $request->attributes->set('foo', 'foo');
91 $controller = function ($foo) {};
93 $this->assertEquals(array('foo'), self::$resolver->getArguments($request, $controller));
96 public function testGetArgumentsUsesDefaultValueFromClosure()
98 $request = Request::create('/');
99 $request->attributes->set('foo', 'foo');
100 $controller = function ($foo, $bar = 'bar') {};
102 $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller));
105 public function testGetArgumentsFromInvokableObject()
107 $request = Request::create('/');
108 $request->attributes->set('foo', 'foo');
109 $controller = new self();
111 $this->assertEquals(array('foo', null), self::$resolver->getArguments($request, $controller));
113 // Test default bar overridden by request attribute
114 $request->attributes->set('bar', 'bar');
116 $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller));
119 public function testGetArgumentsFromFunctionName()
121 $request = Request::create('/');
122 $request->attributes->set('foo', 'foo');
123 $request->attributes->set('foobar', 'foobar');
124 $controller = __NAMESPACE__.'\controller_function';
126 $this->assertEquals(array('foo', 'foobar'), self::$resolver->getArguments($request, $controller));
129 public function testGetArgumentsFailsOnUnresolvedValue()
131 $request = Request::create('/');
132 $request->attributes->set('foo', 'foo');
133 $request->attributes->set('foobar', 'foobar');
134 $controller = array(new self(), 'controllerWithFooBarFoobar');
137 self::$resolver->getArguments($request, $controller);
138 $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
139 } catch (\Exception $e) {
140 $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
144 public function testGetArgumentsInjectsRequest()
146 $request = Request::create('/');
147 $controller = array(new self(), 'controllerWithRequest');
149 $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request');
152 public function testGetArgumentsInjectsExtendingRequest()
154 $request = ExtendingRequest::create('/');
155 $controller = array(new self(), 'controllerWithExtendingRequest');
157 $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request when extended');
163 public function testGetVariadicArguments()
165 $request = Request::create('/');
166 $request->attributes->set('foo', 'foo');
167 $request->attributes->set('bar', array('foo', 'bar'));
168 $controller = array(new VariadicController(), 'action');
170 $this->assertEquals(array('foo', 'foo', 'bar'), self::$resolver->getArguments($request, $controller));
175 * @expectedException \InvalidArgumentException
177 public function testGetVariadicArgumentsWithoutArrayInRequest()
179 $request = Request::create('/');
180 $request->attributes->set('foo', 'foo');
181 $request->attributes->set('bar', 'foo');
182 $controller = array(new VariadicController(), 'action');
184 self::$resolver->getArguments($request, $controller);
189 * @expectedException \InvalidArgumentException
191 public function testGetArgumentWithoutArray()
193 $factory = new ArgumentMetadataFactory();
194 $valueResolver = $this->getMockBuilder(ArgumentValueResolverInterface::class)->getMock();
195 $resolver = new ArgumentResolver($factory, array($valueResolver));
197 $valueResolver->expects($this->any())->method('supports')->willReturn(true);
198 $valueResolver->expects($this->any())->method('resolve')->willReturn('foo');
200 $request = Request::create('/');
201 $request->attributes->set('foo', 'foo');
202 $request->attributes->set('bar', 'foo');
203 $controller = array($this, 'controllerWithFooAndDefaultBar');
204 $resolver->getArguments($request, $controller);
208 * @expectedException \RuntimeException
210 public function testIfExceptionIsThrownWhenMissingAnArgument()
212 $request = Request::create('/');
213 $controller = array($this, 'controllerWithFoo');
215 self::$resolver->getArguments($request, $controller);
221 public function testGetNullableArguments()
223 $request = Request::create('/');
224 $request->attributes->set('foo', 'foo');
225 $request->attributes->set('bar', new \stdClass());
226 $request->attributes->set('mandatory', 'mandatory');
227 $controller = array(new NullableController(), 'action');
229 $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), self::$resolver->getArguments($request, $controller));
235 public function testGetNullableArgumentsWithDefaults()
237 $request = Request::create('/');
238 $request->attributes->set('mandatory', 'mandatory');
239 $controller = array(new NullableController(), 'action');
241 $this->assertEquals(array(null, null, 'value', 'mandatory'), self::$resolver->getArguments($request, $controller));
244 public function __invoke($foo, $bar = null)
248 public function controllerWithFoo($foo)
252 public function controllerWithoutArguments()
256 protected function controllerWithFooAndDefaultBar($foo, $bar = null)
260 protected function controllerWithFooBarFoobar($foo, $bar, $foobar)
264 protected function controllerWithRequest(Request $request)
268 protected function controllerWithExtendingRequest(ExtendingRequest $request)
273 function controller_function($foo, $foobar)