Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何对Symfony2控制器进行单元测试?_Php_Unit Testing_Symfony - Fatal编程技术网

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

Php 如何对Symfony2控制器进行单元测试?,php,unit-testing,symfony,Php,Unit Testing,Symfony,我希望尽可能多地使用测试驱动开发——这是一种很好的工作方式 Symfony2控制器创建并返回一个新的响应对象,这让我很困扰 我希望能够独立地对控制器进行单元测试 你是怎么做到的 将控制器创建为普通的旧PHP对象,将其注册为服务,并使用依赖项注入将新的响应对象(或响应工厂)传递到其中,这是解决方案吗?使用mock将模型和其他对象与主控制器方法的逻辑隔离,请参阅 我认为在旧版本中,您可以模拟整个类,但在我拥有的最新phpunit3.6.10中,它似乎不起作用。所以我猜你只剩下依赖注射模式了 clas

我希望尽可能多地使用测试驱动开发——这是一种很好的工作方式

Symfony2控制器创建并返回一个新的
响应
对象,这让我很困扰

我希望能够独立地对控制器进行单元测试

你是怎么做到的


将控制器创建为普通的旧PHP对象,将其注册为服务,并使用依赖项注入将新的
响应
对象(或
响应
工厂)传递到其中,这是解决方案吗?

使用mock将模型和其他对象与主控制器方法的逻辑隔离,请参阅

我认为在旧版本中,您可以模拟整个类,但在我拥有的最新phpunit3.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());
    }
}

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

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

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

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

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

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


    • 刘易斯-我想我会跳到这里来。上述方法使您能够在测试中复制操作逻辑的更好部分。这并没有错,许多框架(尤其是Rails中的RSPEC)实际上建议您在控制器对象上执行单元测试和功能测试。然而,考虑到你的例子,我想我应该跳过单元测试,转而使用函数方法

      在我看来,测试的目的是创建一个沙盒环境,运行测试,并检查副作用和直接结果。如果您的大部分测试都是隔离方法,那么可能是时候使用不同的测试方法或不同的方法来编写类了。考虑到这是一个控制器,并且它们自然地将堆栈的不同部分粘合在一起,我将创建堆栈上更远的沙箱。具体而言,我将使用如下方法:

      对我来说效果很好:)

      单元测试 将控制器重构为服务:

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

      功能测试
      当然(正如其他人已经提到的),您可以使用
      WebTestCase
      ,如下所述:

      Totaly-但是这些对象(包括响应对象)将在控制器中实例化。除非我使用DI容器为控制器提供模型和其他东西。也许我可以创建一个响应工厂服务,并从DI容器中获取它-这样它(DI容器和工厂)就可以被模拟来单独测试控制器类。它返回
      响应
      对象到底有什么问题?什么都没有。我只是不喜欢在控制器中创建响应对象。我是依赖注入的坚定信徒,我讨厌在DI容器之外的任何东西中看到“new”关键字。也许这个信念是错误的,好吧。我认为,由于控制器是一个类,它也需要进行单元测试。我不喜欢在编写测试之前编写代码的想法,所以我想知道是否有一种方法可以重构控制器的使用方式,以便能够对其进行单元测试。我想我仍然可以通过在编写控制器之前编写功能测试来使用TDD。Symfony并不正式推荐将控制器定义为服务。一些开发人员将它们用于非常特定的用例,例如DDD(域驱动设计)和六边形体系结构应用程序。谁说的?在他们自己的文件中,赞成者多于反对者。我很确定在未来版本的symfony中将支持控制器作为服务,所以我不会太担心它“不是官方推荐的”。