Skip to content

Commit 0b9243b

Browse files
committed
fix tests
1 parent 8535416 commit 0b9243b

File tree

9 files changed

+647
-599
lines changed

9 files changed

+647
-599
lines changed

src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
2121
use Symfony\Component\DependencyInjection\ContainerInterface;
2222
use Symfony\Component\HttpFoundation\Request;
23-
use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest;
23+
use Symfony\Component\HttpKernel\Test\Controller\ContainerControllerResolverTestCase;
2424

25-
class ControllerResolverTest extends ContainerControllerResolverTest
25+
class ControllerResolverTest extends ContainerControllerResolverTestCase
2626
{
2727
public function testGetControllerOnContainerAware()
2828
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\Test\Controller;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\Debug\ErrorHandler;
17+
use Symfony\Component\DependencyInjection\Container;
18+
use Symfony\Component\HttpFoundation\Request;
19+
use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
20+
21+
/**
22+
* @internal
23+
*/
24+
class ContainerControllerResolverTestCase extends ControllerResolverTestCase
25+
{
26+
public function testGetControllerService()
27+
{
28+
$container = $this->createMockContainer();
29+
$container->expects($this->once())
30+
->method('has')
31+
->with('foo')
32+
->willReturn(true);
33+
$container->expects($this->once())
34+
->method('get')
35+
->with('foo')
36+
->willReturn($this)
37+
;
38+
39+
$resolver = $this->createControllerResolver(null, $container);
40+
$request = Request::create('/');
41+
$request->attributes->set('_controller', 'foo:controllerMethod1');
42+
43+
$controller = $resolver->getController($request);
44+
45+
$this->assertInstanceOf(\get_class($this), $controller[0]);
46+
$this->assertSame('controllerMethod1', $controller[1]);
47+
}
48+
49+
public function testGetControllerInvokableService()
50+
{
51+
$invokableController = new InvokableController('bar');
52+
53+
$container = $this->createMockContainer();
54+
$container->expects($this->once())
55+
->method('has')
56+
->with('foo')
57+
->willReturn(true)
58+
;
59+
$container->expects($this->once())
60+
->method('get')
61+
->with('foo')
62+
->willReturn($invokableController)
63+
;
64+
65+
$resolver = $this->createControllerResolver(null, $container);
66+
$request = Request::create('/');
67+
$request->attributes->set('_controller', 'foo');
68+
69+
$controller = $resolver->getController($request);
70+
71+
$this->assertEquals($invokableController, $controller);
72+
}
73+
74+
public function testGetControllerInvokableServiceWithClassNameAsName()
75+
{
76+
$invokableController = new InvokableController('bar');
77+
$className = __NAMESPACE__.'\InvokableController';
78+
79+
$container = $this->createMockContainer();
80+
$container->expects($this->once())
81+
->method('has')
82+
->with($className)
83+
->willReturn(true)
84+
;
85+
$container->expects($this->once())
86+
->method('get')
87+
->with($className)
88+
->willReturn($invokableController)
89+
;
90+
91+
$resolver = $this->createControllerResolver(null, $container);
92+
$request = Request::create('/');
93+
$request->attributes->set('_controller', $className);
94+
95+
$controller = $resolver->getController($request);
96+
97+
$this->assertEquals($invokableController, $controller);
98+
}
99+
100+
public function testNonInstantiableController()
101+
{
102+
$container = $this->createMockContainer();
103+
$container->expects($this->once())
104+
->method('has')
105+
->with(NonInstantiableController::class)
106+
->willReturn(false)
107+
;
108+
109+
$resolver = $this->createControllerResolver(null, $container);
110+
$request = Request::create('/');
111+
$request->attributes->set('_controller', [NonInstantiableController::class, 'action']);
112+
113+
$controller = $resolver->getController($request);
114+
115+
$this->assertSame([NonInstantiableController::class, 'action'], $controller);
116+
}
117+
118+
public function testNonConstructController()
119+
{
120+
$this->expectException('LogicException');
121+
$this->expectExceptionMessage('Controller "Symfony\Component\HttpKernel\Test\Controller\ImpossibleConstructController" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?');
122+
$container = $this->getMockBuilder(Container::class)->getMock();
123+
$container->expects($this->at(0))
124+
->method('has')
125+
->with(ImpossibleConstructController::class)
126+
->willReturn(true)
127+
;
128+
129+
$container->expects($this->at(1))
130+
->method('has')
131+
->with(ImpossibleConstructController::class)
132+
->willReturn(false)
133+
;
134+
135+
$container->expects($this->atLeastOnce())
136+
->method('getRemovedIds')
137+
->with()
138+
->willReturn([ImpossibleConstructController::class => true])
139+
;
140+
141+
$resolver = $this->createControllerResolver(null, $container);
142+
$request = Request::create('/');
143+
$request->attributes->set('_controller', [ImpossibleConstructController::class, 'action']);
144+
145+
if (\PHP_VERSION_ID < 70100) {
146+
ErrorHandler::register();
147+
try {
148+
$resolver->getController($request);
149+
} finally {
150+
restore_error_handler();
151+
restore_exception_handler();
152+
}
153+
} else {
154+
$resolver->getController($request);
155+
}
156+
}
157+
158+
public function testNonInstantiableControllerWithCorrespondingService()
159+
{
160+
$service = new \stdClass();
161+
162+
$container = $this->createMockContainer();
163+
$container->expects($this->atLeastOnce())
164+
->method('has')
165+
->with(NonInstantiableController::class)
166+
->willReturn(true)
167+
;
168+
$container->expects($this->atLeastOnce())
169+
->method('get')
170+
->with(NonInstantiableController::class)
171+
->willReturn($service)
172+
;
173+
174+
$resolver = $this->createControllerResolver(null, $container);
175+
$request = Request::create('/');
176+
$request->attributes->set('_controller', [NonInstantiableController::class, 'action']);
177+
178+
$controller = $resolver->getController($request);
179+
180+
$this->assertSame([$service, 'action'], $controller);
181+
}
182+
183+
public function testExceptionWhenUsingRemovedControllerService()
184+
{
185+
$this->expectException('LogicException');
186+
$this->expectExceptionMessage('Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?');
187+
$container = $this->getMockBuilder(Container::class)->getMock();
188+
$container->expects($this->at(0))
189+
->method('has')
190+
->with('app.my_controller')
191+
->willReturn(false)
192+
;
193+
194+
$container->expects($this->atLeastOnce())
195+
->method('getRemovedIds')
196+
->with()
197+
->willReturn(['app.my_controller' => true])
198+
;
199+
200+
$resolver = $this->createControllerResolver(null, $container);
201+
202+
$request = Request::create('/');
203+
$request->attributes->set('_controller', 'app.my_controller');
204+
$resolver->getController($request);
205+
}
206+
207+
public function testExceptionWhenUsingControllerWithoutAnInvokeMethod()
208+
{
209+
$this->expectException('LogicException');
210+
$this->expectExceptionMessage('Controller "app.my_controller" cannot be called without a method name. Did you forget an "__invoke" method?');
211+
$container = $this->getMockBuilder(Container::class)->getMock();
212+
$container->expects($this->once())
213+
->method('has')
214+
->with('app.my_controller')
215+
->willReturn(true)
216+
;
217+
$container->expects($this->once())
218+
->method('get')
219+
->with('app.my_controller')
220+
->willReturn(new ImpossibleConstructController('toto', 'controller'))
221+
;
222+
223+
$resolver = $this->createControllerResolver(null, $container);
224+
225+
$request = Request::create('/');
226+
$request->attributes->set('_controller', 'app.my_controller');
227+
$resolver->getController($request);
228+
}
229+
230+
/**
231+
* @dataProvider getUndefinedControllers
232+
*/
233+
public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null)
234+
{
235+
// All this logic needs to be duplicated, since calling parent::testGetControllerOnNonUndefinedFunction will override the expected excetion and not use the regex
236+
$resolver = $this->createControllerResolver();
237+
$this->expectException($exceptionName);
238+
$this->expectExceptionMessageRegExp($exceptionMessage);
239+
240+
$request = Request::create('/');
241+
$request->attributes->set('_controller', $controller);
242+
$resolver->getController($request);
243+
}
244+
245+
public function getUndefinedControllers()
246+
{
247+
return [
248+
['foo', \LogicException::class, '/Controller not found: service "foo" does not exist\./'],
249+
['oof::bar', \InvalidArgumentException::class, '/Class "oof" does not exist\./'],
250+
['stdClass', \LogicException::class, '/Controller not found: service "stdClass" does not exist\./'],
251+
[
252+
'Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTest::bar',
253+
\InvalidArgumentException::class,
254+
'/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/',
255+
],
256+
];
257+
}
258+
259+
protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null)
260+
{
261+
if (!$container) {
262+
$container = $this->createMockContainer();
263+
}
264+
265+
return new ContainerControllerResolver($container, $logger);
266+
}
267+
268+
protected function createMockContainer()
269+
{
270+
return $this->getMockBuilder(ContainerInterface::class)->getMock();
271+
}
272+
}
273+
274+
class InvokableController
275+
{
276+
public function __construct($bar) // mandatory argument to prevent automatic instantiation
277+
{
278+
}
279+
280+
public function __invoke()
281+
{
282+
}
283+
}
284+
285+
abstract class NonInstantiableController
286+
{
287+
public static function action()
288+
{
289+
}
290+
}
291+
292+
class ImpossibleConstructController
293+
{
294+
public function __construct($toto, $controller)
295+
{
296+
}
297+
298+
public function action()
299+
{
300+
}
301+
}

0 commit comments

Comments
 (0)