繁体   English   中英

如何对Symfony控制器进行单元测试

[英]How to unit test Symfony controllers

我正在尝试使用Codeception在测试工具中获取Symfony控制器。 每个方法都从如下开始:

public function saveAction(Request $request, $id)
{
    // Entity management
    /** @var EntityManager $em */
    $em = $this->getDoctrine()->getManager();

    /* Actual code here
    ...
    */
}

public function submitAction(Request $request, $id)
{
    // Entity management
    /** @var EntityManager $em */
    $em = $this->getDoctrine()->getManager();

    /* 200+ lines of procedural code here
    ...
    */
}

我试过了:

$request = \Symfony\Component\HttpFoundation\Request::create(
    $uri, $method, $parameters, $cookies, $files, $server, $content);

$my_controller = new MyController();
$my_controller->submitAction($request, $id);

从我的单元测试,但似乎有很多其他设置,我不知道Symfony在后台做了什么。 每当我找到一个丢失的对象并对其进行初始化时,就会有另一个在某个时刻失败。

我也试过从PhpStorm中逐步完成测试,但是PhpUnit有一些输出会导致Symfony在我试图测试的代码附近死掉之前因为它在任何输出发生后都无法启动$_SESSION 我不认为这是从命令行发生的,但我还不是很接近。

如何在单元测试中简单且可扩展地运行此代码?


一点背景:

我继承了这段代码。 我知道它很脏并且闻起来因为它在控制器中进行模型逻辑。 我知道我所要求的并不是一个“纯粹的”单元测试,因为它几乎涉及整个应用程序。

但我需要能够自动运行这个“小”(200+行)的代码。 代码应该运行不超过几秒钟。 我不知道多久,因为我从来没有能够独立运行它。

目前,通过网站运行此代码的设置时间很长,而且很复杂。 代码不生成网页,它基本上是一个生成文件的API调用。 我需要能够在很短的时间内生成尽可能多的这些测试文件,因为我正在进行编码更改。

代码就是这样。 我的工作是能够对其进行更改,而且目前我甚至无法在没有巨大开销的情况下运行它。 在不知道它在做什么的情况下对其进行更改是不负责任的。

部分问题是,当您编写从Symfony的基本Controller或新的AbstractController扩展的Controller时,它将从容器中加载其他依赖项。 这些服务要么必须在测试中实例化并将它们传递给容器,然后在控制器中设置如下:

$loader = new Twig_Loader_Filesystem('/path/to/project/app/Resources/views');
$twig = new Twig_Environment($loader, array(
    'cache' => '/path/to/app/var/cache/templates',
));

# ... other services like routing, doctrine and token_storage

$container = new Container();
$container->set('twig', $twig);

$controller = new MyController();
$controller->setContainer($container);

或者嘲笑它们,这使得你的测试几乎不可读,并且在你对代码所做的每一次改变中都会中断。

正如您所看到的,这不是一个单元测试,因为您将需要通过调用$this->get()/$this->container->get()或间接调用您从容器中提取的所有服务。通过控制器中的辅助方法,例如getDoctrine()

如果您不以与在生产中使用相同的方式配置服务,这不仅繁琐,您的测试可能不是很有意义,因为它们可能会通过您的测试但在生产中失败。

问题的另一部分是您的代码段内的评论:

这里有200多行程序代码

没有看到代码,我可以告诉你,正确的单元测试这几乎是不可能的,不值得。

简短的回答是,你做不到。

我建议使用WebTestCase编写功能测试使用CodeCeption编写Selenium,并通过UI间接测试控制器。

一旦您完成了涵盖操作(主要)功能的测试,您就可以开始重构您的控制器,将事物分成更小的块和更容易测试的服务。 对于那些新类,单元测试是有意义的。 当您的功能测试为绿色(再次)时,您将知道网站何时再次发生变化。 理想情况下,您不需要更改这些首次测试,因为它们只通过浏览器查看您的网站,因此不会受到您所做的任何代码更改的影响。 请注意不要对模板和路由进行更改。

我发现只需要一些简短的线就可以将Symfony变成测试工具:

// Load the autoloader class so that the controller can find everything it needs
//$loader = require 'app/vendor/autoload.php';
require 'app/vendor/autoload.php';

// Create a new Symfony kernel instance
$kernel = new \AppKernel('prod', false);
//$kernel = new \AppKernel('dev', true);
// Boot the kernel
$kernel->boot();
// Get the kernel container
$container = $kernel->getContainer();
// Services can be retrieved like so if you need to
//$service = $container->get('name.of.registered.service');

// Create a new instance of your controller
$controller = new \What\You\Call\Your\Bundle\Controller\FooBarController();
// You MUST set the container for it to work properly
$controller->setContainer($container);

在此代码之后,您可以测试控制器上的任何公共方法。 当然,如果您正在测试生产代码(因为我必须这样做;我的开发代码完全不同,因为代码库写得非常糟糕),请注意您可能正在触摸数据库,进行Web调用等。

但是,好处是您可以开始对控制器进行代码覆盖,以了解它们无法正常工作的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM