繁体   English   中英

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

[英]How can I unit test a Symfony2 controller?

我想尽可能地使用测试驱动开发 - 这是一种很好的工作方式。

我对Symfony2控制器创建并返回一个新的Response对象这一事实感到不安。

我希望能够单独测试控制器。

你怎么做呢?

是否将控制器创建为Plain Old PHP Object,将其注册为服务并使用依赖注入将新的Response对象(或Response工厂)传递给它?

通常,您的控制器将不同的对象插入在一起并按正确的顺序连接它们。 也许他调用一个存储库,读取一些对象并通过render方法返回它们。 也许他会打电话给其他一些做事的其他经理/经理。

这意味着控制器是高级组件。 通常情况下,这表明功能测试是按顺序而不是单元测试。 您不应该通过单元测试获得100%的代码覆盖率。 也许你可以这样想:如果你对控制器调用的所有内容(模型,验证,表单,存储库)进行单元测试,那么可能出现什么问题? 大多数时候,只有在生产中使用所有真正的类时才会观察到它。

我还想指出,TDD并不意味着一切都必须经过单元测试。 可以对高级代码进行一些功能测试。 如上所述,如果使用单元测试测试低级组件,则只应测试它们如何协同工作,而不能使用模拟测试,因为您告诉模拟返回值是什么。

如果您的控制器不仅仅是将系统的各个部分插在一起,那么您应该考虑将这些内容重构为更多的低级类,您可以使用单元测试进行测试。

所以我的建议是使用功能测试来测试你的控制器并使用单元测试来测试你的模型和你的业务逻辑。

如果您在使用功能测试时遇到困难,可以阅读以下内容:

使用模拟从主控制器方法的逻辑中隔离模型和其他对象,请参阅http://www.phpunit.de/manual/3.7/en/test-doubles.html#test-doubles.mock-objects

我认为在旧版本中你可以模拟整个类,但最新的phpunit 3.6.10,我有它似乎不起作用。 所以我猜你会留下依赖注入模式

class objss{
    function ss(){
        $x = new zz();
        var_dump($x->z());
    }
}



class MoTest extends PHPUnit_Framework_TestCase{
    public function setUp(){

    }

    public function testA(){
        $class = $this->getMock('zzMock', array('z'), array(), 'zz');
        $class->expects($this->any())->method('z')->will($this->returnValue('2'));

        $obj = new objss();
        $this->assertEquals('2', $obj->ss());
    }
}

单元测试

将您的控制器重构为服务: http//symfony.com/doc/current/cookbook/controller/service.html

然后你可以轻松地对它们进行单元测

功能测试

当然(正如其他人已经提到的那样)你可以使用这里描述的WebTestCasehttpWebTestCase

刘易斯 - 我以为我会跳进这里。 上面的方法让您在测试中复制动作逻辑的更好部分。 这没有什么不对,很多框架(特别是Rails中的RSPEC)实际上建议你对Controller对象进行单元测试以及功能测试。 但是,根据你的例子,我想我会跳过单元测试并去寻找功能方法。

在我看来,测试的重点是创建一个沙盒环境,运行测试,并检查副作用和直接结果。 如果你达到了大部分测试都是隔离方法的程度,那么可能是时候采用不同的测试方法或者编写类的不同方法。 鉴于这是一个控制器,并且本质上它们将不同的堆栈部分粘合在一起,我会在堆栈中创建更远的沙箱。 具体来说,我会使用这样的方法:

https://github.com/PolishSymfonyCommunity/SymfonyMockerContainer

为我工作很棒:)

暂无
暂无

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

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