1

我在为 Symonfy2 包中的控制器编写测试时遇到了问题。

控制器只能通过 Twig's 访问{% render %},并且在应用程序中运行良好,但无论我采用哪种方式,测试都会失败。这基本上是发生了什么:

控制器A。- “父”控制器。通过典型的 URL 加载。

控制器B{% render %}通过从 Controller 呈现的模板加载AB一个对象变量在{% render %}标签 中被传递给 Controller 。

控制器C{% render %}通过从 Controller 呈现的模板加载B

这一切在实际应用程序中都非常有效,并且以这种方式构造事物可以最大程度地重用代码。当我开始为 Controller 编写单元测试时,问题就出现了B。因为这是一个内部唯一的控制器,我认为最好这样调用测试方法:

$this->obj = new ControllerB();
$this->obj->setContainer($this->getContainer());
$this->obj->methodToTest();

但这导致我收到此错误消息:

Twig_Error_Runtime:在第 XX 行渲染模板(“您无法创建非活动范围(“请求”)的服务(“请求”)。”)期间引发异常 -这是我们尝试的行通过 {% render %} 从 Controller C 渲染一个方法

因此,似乎因为对 ControllerB中方法的调用不是请求的一部分,所以它不能向 controller 发出内部子请求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 %}在模板中使用(内部子请求)的控制器方法的东西。以前有人遇到过这个吗?

4

1 回答 1

0

我知道我有点,但在这里我的建议:

如果你真的想这样做,你可以让你的控制器成为一个服务,给它所有它需要的依赖,然后编写一个单元测试。见http://php-and-symfony.matthiasnoback.nl/2012/06/symfony2-testing-your-controllers/

但我建议您不要对控制器进行单元测试。如果它们写得好,它们不包含任何业务逻辑,并且对它们进行单元测试是毫无意义的。如果有关联的路由(但在这种情况下你不能直接给它对象),你应该直接对你的控制器进行功能测试,否则如果控制器不是设计为直接从浏览器访问的(因为你给它对象,或者只是因为你不想),只需测试包含它的控制器,它将覆盖两个控制器。在您的示例中,只需测试控制器 A,它就隐含地涵盖了 B 和 C。

于 2013-06-04T17:01:43.597 回答