Symfony2 - 为正在将对象作为参数传递的控制器编写测试的问题

时间:2013-01-31 14:31:51

标签: symfony phpunit twig

我遇到了为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 %}(内部子请求)的东西。有没有人遇到过这个?

1 个答案:

答案 0 :(得分:0)

我知道我有点但在这里我的意见是:

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

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