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\HttpFoundation\Session\Session;
16 use Symfony\Component\HttpFoundation\Session\SessionInterface;
17 use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
18 use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
19 use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
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\ExtendingSession;
24 use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController;
25 use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController;
26 use Symfony\Component\HttpFoundation\Request;
28 class ArgumentResolverTest extends TestCase
30 /** @var ArgumentResolver */
31 private static $resolver;
33 public static function setUpBeforeClass()
35 $factory = new ArgumentMetadataFactory();
37 self::$resolver = new ArgumentResolver($factory);
40 public function testDefaultState()
42 $this->assertEquals(self::$resolver, new ArgumentResolver());
43 $this->assertNotEquals(self::$resolver, new ArgumentResolver(null, array(new RequestAttributeValueResolver())));
46 public function testGetArguments()
48 $request = Request::create('/');
49 $request->attributes->set('foo', 'foo');
50 $controller = array(new self(), 'controllerWithFoo');
52 $this->assertEquals(array('foo'), self::$resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method');
55 public function testGetArgumentsReturnsEmptyArrayWhenNoArguments()
57 $request = Request::create('/');
58 $controller = array(new self(), 'controllerWithoutArguments');
60 $this->assertEquals(array(), self::$resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments');
63 public function testGetArgumentsUsesDefaultValue()
65 $request = Request::create('/');
66 $request->attributes->set('foo', 'foo');
67 $controller = array(new self(), 'controllerWithFooAndDefaultBar');
69 $this->assertEquals(array('foo', null), self::$resolver->getArguments($request, $controller), '->getArguments() uses default values if present');
72 public function testGetArgumentsOverrideDefaultValueByRequestAttribute()
74 $request = Request::create('/');
75 $request->attributes->set('foo', 'foo');
76 $request->attributes->set('bar', 'bar');
77 $controller = array(new self(), 'controllerWithFooAndDefaultBar');
79 $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes');
82 public function testGetArgumentsFromClosure()
84 $request = Request::create('/');
85 $request->attributes->set('foo', 'foo');
86 $controller = function ($foo) {};
88 $this->assertEquals(array('foo'), self::$resolver->getArguments($request, $controller));
91 public function testGetArgumentsUsesDefaultValueFromClosure()
93 $request = Request::create('/');
94 $request->attributes->set('foo', 'foo');
95 $controller = function ($foo, $bar = 'bar') {};
97 $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller));
100 public function testGetArgumentsFromInvokableObject()
102 $request = Request::create('/');
103 $request->attributes->set('foo', 'foo');
104 $controller = new self();
106 $this->assertEquals(array('foo', null), self::$resolver->getArguments($request, $controller));
108 // Test default bar overridden by request attribute
109 $request->attributes->set('bar', 'bar');
111 $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller));
114 public function testGetArgumentsFromFunctionName()
116 $request = Request::create('/');
117 $request->attributes->set('foo', 'foo');
118 $request->attributes->set('foobar', 'foobar');
119 $controller = __NAMESPACE__.'\controller_function';
121 $this->assertEquals(array('foo', 'foobar'), self::$resolver->getArguments($request, $controller));
124 public function testGetArgumentsFailsOnUnresolvedValue()
126 $request = Request::create('/');
127 $request->attributes->set('foo', 'foo');
128 $request->attributes->set('foobar', 'foobar');
129 $controller = array(new self(), 'controllerWithFooBarFoobar');
132 self::$resolver->getArguments($request, $controller);
133 $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
134 } catch (\Exception $e) {
135 $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
139 public function testGetArgumentsInjectsRequest()
141 $request = Request::create('/');
142 $controller = array(new self(), 'controllerWithRequest');
144 $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request');
147 public function testGetArgumentsInjectsExtendingRequest()
149 $request = ExtendingRequest::create('/');
150 $controller = array(new self(), 'controllerWithExtendingRequest');
152 $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request when extended');
158 public function testGetVariadicArguments()
160 $request = Request::create('/');
161 $request->attributes->set('foo', 'foo');
162 $request->attributes->set('bar', array('foo', 'bar'));
163 $controller = array(new VariadicController(), 'action');
165 $this->assertEquals(array('foo', 'foo', 'bar'), self::$resolver->getArguments($request, $controller));
170 * @expectedException \InvalidArgumentException
172 public function testGetVariadicArgumentsWithoutArrayInRequest()
174 $request = Request::create('/');
175 $request->attributes->set('foo', 'foo');
176 $request->attributes->set('bar', 'foo');
177 $controller = array(new VariadicController(), 'action');
179 self::$resolver->getArguments($request, $controller);
184 * @expectedException \InvalidArgumentException
186 public function testGetArgumentWithoutArray()
188 $factory = new ArgumentMetadataFactory();
189 $valueResolver = $this->getMockBuilder(ArgumentValueResolverInterface::class)->getMock();
190 $resolver = new ArgumentResolver($factory, array($valueResolver));
192 $valueResolver->expects($this->any())->method('supports')->willReturn(true);
193 $valueResolver->expects($this->any())->method('resolve')->willReturn('foo');
195 $request = Request::create('/');
196 $request->attributes->set('foo', 'foo');
197 $request->attributes->set('bar', 'foo');
198 $controller = array($this, 'controllerWithFooAndDefaultBar');
199 $resolver->getArguments($request, $controller);
203 * @expectedException \RuntimeException
205 public function testIfExceptionIsThrownWhenMissingAnArgument()
207 $request = Request::create('/');
208 $controller = array($this, 'controllerWithFoo');
210 self::$resolver->getArguments($request, $controller);
216 public function testGetNullableArguments()
218 $request = Request::create('/');
219 $request->attributes->set('foo', 'foo');
220 $request->attributes->set('bar', new \stdClass());
221 $request->attributes->set('mandatory', 'mandatory');
222 $controller = array(new NullableController(), 'action');
224 $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), self::$resolver->getArguments($request, $controller));
230 public function testGetNullableArgumentsWithDefaults()
232 $request = Request::create('/');
233 $request->attributes->set('mandatory', 'mandatory');
234 $controller = array(new NullableController(), 'action');
236 $this->assertEquals(array(null, null, 'value', 'mandatory'), self::$resolver->getArguments($request, $controller));
239 public function testGetSessionArguments()
241 $session = new Session(new MockArraySessionStorage());
242 $request = Request::create('/');
243 $request->setSession($session);
244 $controller = array($this, 'controllerWithSession');
246 $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
249 public function testGetSessionArgumentsWithExtendedSession()
251 $session = new ExtendingSession(new MockArraySessionStorage());
252 $request = Request::create('/');
253 $request->setSession($session);
254 $controller = array($this, 'controllerWithExtendingSession');
256 $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
259 public function testGetSessionArgumentsWithInterface()
261 $session = $this->getMockBuilder(SessionInterface::class)->getMock();
262 $request = Request::create('/');
263 $request->setSession($session);
264 $controller = array($this, 'controllerWithSessionInterface');
266 $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
270 * @expectedException \RuntimeException
272 public function testGetSessionMissMatchWithInterface()
274 $session = $this->getMockBuilder(SessionInterface::class)->getMock();
275 $request = Request::create('/');
276 $request->setSession($session);
277 $controller = array($this, 'controllerWithExtendingSession');
279 self::$resolver->getArguments($request, $controller);
283 * @expectedException \RuntimeException
285 public function testGetSessionMissMatchWithImplementation()
287 $session = new Session(new MockArraySessionStorage());
288 $request = Request::create('/');
289 $request->setSession($session);
290 $controller = array($this, 'controllerWithExtendingSession');
292 self::$resolver->getArguments($request, $controller);
296 * @expectedException \RuntimeException
298 public function testGetSessionMissMatchOnNull()
300 $request = Request::create('/');
301 $controller = array($this, 'controllerWithExtendingSession');
303 self::$resolver->getArguments($request, $controller);
306 public function __invoke($foo, $bar = null)
310 public function controllerWithFoo($foo)
314 public function controllerWithoutArguments()
318 protected function controllerWithFooAndDefaultBar($foo, $bar = null)
322 protected function controllerWithFooBarFoobar($foo, $bar, $foobar)
326 protected function controllerWithRequest(Request $request)
330 protected function controllerWithExtendingRequest(ExtendingRequest $request)
334 protected function controllerWithSession(Session $session)
338 protected function controllerWithSessionInterface(SessionInterface $session)
342 protected function controllerWithExtendingSession(ExtendingSession $session)
347 function controller_function($foo, $foobar)