我遇到了为Symonfy2软件包中的控制器编写测试的问题。
控制器只能通过Twig的{% render %}
访问,并且在应用程序中运行良好,但无论我采用何种方式,测试都会失败。基本上是这样:
控制器A
。 - “父”控制器。通过典型的URL加载。
控制器B
。从Controller {% render %}
呈现的模板通过A
加载。对象变量将传递到B
标记中的Controller {% render %}
。
控制器C
。从Controller {% render %}
呈现的模板通过B
加载。
这在实际应用程序中运行良好,并且以这种方式构造的事物允许最大量的代码重用。当我开始为Controller B
编写单元测试时,会出现此问题。因为这是一个内部唯一的控制器,我认为最好调用这样的测试方法:
$this->obj = new ControllerB();
$this->obj->setContainer($this->getContainer());
$this->obj->methodToTest();
但是这引出了我的错误信息:
Twig_Error_Runtime:在呈现模板期间抛出异常(“您无法创建非活动范围的服务(”请求“)(”请求“)。”)在第XX行 - 这是我们尝试通过{%render%}
从Controller C渲染方法的行
因此,似乎因为对Controller B
中的方法的调用不是请求的一部分,所以它不能向控制器C
发出内部子请求。解决方案似乎是通过以下方式向控制器B
发出请求:
$this->client = static::createClient(...);
$crawler = $this->client->request('GET', '/routeToControllerB');
但是这不起作用,因为我需要将对象和数组传递给Controller B
中的方法,并且它们太大而不能serialize/json_encode
并且适合要请求的URL。
我已经尝试过尝试强制将请求放入对象容器中:
$this->client = static::createClient();
$this->client->followRedirects();
$container = $this->getContainer();
$container->get('session')->start();
$request = Request::createFromGlobals();
$container->set('request', $request);
$user = new \User(1111);
\Auth::set_user($user);
$user = new \Company\Component\Security\User\User(\Auth::user());
$token = new UsernamePasswordToken($user, 'phpunit', 'PHPSESSID', $user->getRoles());
$container->get('security.context')->setToken($token);
$this->obj = new ControllerB();
$this->obj->setContainer($container);
但到目前为止,我找不到任何可以让我测试需要传递对象的控制器方法,并在模板中使用{% render %}
(内部子请求)的东西。有没有人遇到过这个?
答案 0 :(得分:0)
我知道我有点但在这里我的意见是:
如果你真的想这样做,你可以让你的控制器成为一个服务,给它所需的所有依赖,然后编写一个单元测试。见http://php-and-symfony.matthiasnoback.nl/2012/06/symfony2-testing-your-controllers/
但我建议你不要对你的控制器进行单元测试。如果它们写得很好,它们不包含任何业务逻辑,单元测试它们就没有意义。 如果存在关联的路径(但在这种情况下,您将无法直接为其提供对象),您应该直接进行控制器的功能测试,否则如果控制器不能直接从浏览器访问(因为你给它对象,或者只是因为你不想这样做,只需测试包含它的控制器,它将覆盖两个控制器。在您的示例中,只需测试控制器A,它隐式地覆盖B和C.