php 如何对 Symfony2 控制器进行单元测试?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10126826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I unit test a Symfony2 controller?
提问by Lewis Bassett
I want to use Test Driven Development as much as possible — it's a great way of working.
我想尽可能多地使用测试驱动开发——这是一种很好的工作方式。
I am troubled by the fact that Symfony2 controllers create and return a new Responseobject.
我对 Symfony2 控制器创建并返回一个新Response对象这一事实感到困扰。
I want to be able to unit test a controller in isolation.
我希望能够单独对控制器进行单元测试。
How do you do it?
你怎么做呢?
Is the answer to create a controller as a Plain Old PHP Object, register it as a service and use Dependency Injection to pass a new Responseobject (or a Responsefactory) into it?
将控制器创建为普通旧 PHP 对象,将其注册为服务并使用依赖注入将新Response对象(或Response工厂)传递给它的答案是什么?
回答by Sgoettschkes
Normally, your controller plugs together different objects and connects them in the correct order. Maybe he calls a repository, reads some objects and returns them through the render method. Maybe he calls some other Handlers/Managers who do stuff.
通常,您的控制器将不同的对象连接在一起并以正确的顺序连接它们。也许他调用一个存储库,读取一些对象并通过render 方法返回它们。也许他会打电话给其他一些做事的处理程序/经理。
This means that a controller is a high level component. More often than not this indicates that functional tests are in order instead of unit tests. You should not aim to get 100% code coverage with your unit tests. Maybe you can think of it that way: If you unit test everything the controller calls (model, validation, form, repository), what could go wrong? Most of the time it's something you only observe when using all the real classes involved when in production.
这意味着控制器是一个高级组件。这通常表明功能测试是有序的,而不是单元测试。您不应该旨在通过单元测试获得 100% 的代码覆盖率。也许您可以这样想:如果您对控制器调用的所有内容(模型、验证、表单、存储库)进行单元测试,会出现什么问题?大多数情况下,只有在使用生产中涉及的所有真实类时才会观察到。
I want also like to point out that TDD does not mean that everything has to be unit-tested. It's ok to have some functional tests for the high-level code. As said, if you test the low-level components with unit-tests you should only test how they are working together which you cannot test with mocks because you tell the mocks what the return value is.
我还想指出,TDD 并不意味着一切都必须经过单元测试。可以对高级代码进行一些功能测试。如前所述,如果您使用单元测试测试低级组件,您应该只测试它们如何协同工作,而不能使用模拟进行测试,因为您告诉模拟返回值是什么。
If your controller does more than plugging parts of the system together you should think about refactoring the stuff into more low-level classes you can test with unit-tests.
如果您的控制器所做的不仅仅是将系统的各个部分插入在一起,您应该考虑将这些东西重构为更多的低级类,您可以使用单元测试进行测试。
So my suggestionwould be to use functional tests to test your controllers and use unit-tests to test your models and your business logic stuff.
所以我的建议是使用功能测试来测试您的控制器,并使用单元测试来测试您的模型和业务逻辑内容。
If you struggle with functional tests, you can read the following:
如果您在功能测试方面遇到困难,您可以阅读以下内容:
回答by Artjom Kurapov
Use mocks to isolate models and other objects from main controller method's logic, see http://www.phpunit.de/manual/3.7/en/test-doubles.html#test-doubles.mock-objects
使用模拟将模型和其他对象与主控制器方法的逻辑隔离,请参阅http://www.phpunit.de/manual/3.7/en/test-doubles.html#test-doubles.mock-objects
I think that in older versions you could mock entire class, but with latest phpunit 3.6.10 that i have it doesn't seem to work. So i guess you are left with depency injection pattern
我认为在旧版本中您可以模拟整个课程,但是使用我拥有的最新 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());
}
}
回答by Marcel Burkhard
Unit Testing
单元测试
Refactor your controllers to be services: http://symfony.com/doc/current/cookbook/controller/service.html
将您的控制器重构为服务:http: //symfony.com/doc/current/cookbook/controller/service.html
Then you can easily unit test them.
然后您可以轻松地对它们进行单元测试。
Functional Testing
功能测试
Of course (as already mentioned by others) you can use the WebTestCaseas described here: http://symfony.com/doc/current/book/testing.html#functional-tests
当然(正如其他人已经提到的)你可以使用WebTestCase这里描述的:http: //symfony.com/doc/current/book/testing.html#functional-tests
回答by genexp
Lewis - I thought I'd jump in here. The approach above has you replicating the better part of your actions logic in your tests. There's nothing wrong with this, many frameworks (notably RSPEC in Rails) actually suggest you perform both Unit tests on your Controller objects as well as functional tests. However, given your example, I think I'd skip the unit test and go for the functional approach.
刘易斯 - 我以为我会跳在这里。上面的方法让您在测试中复制操作逻辑的更好部分。这没有任何问题,许多框架(尤其是 Rails 中的 RSPEC)实际上建议您对 Controller 对象执行单元测试以及功能测试。但是,鉴于您的示例,我想我会跳过单元测试并采用功能方法。
The point of a test in my mind is to create a sandboxed environment, run the test, and check for side effects and direct result. If you get to a point where most of your test is isolating the method, then its probably time for either a different testing approach or a different approach to writing your class. Given that this is a controller, and by nature they glue together different pieces of the stack, I'd create your sandbox farther up the stack. Specifically, I would use an approach like this:
在我看来,测试的重点是创建一个沙盒环境,运行测试,并检查副作用和直接结果。如果您的大部分测试都在隔离方法,那么可能是时候采用不同的测试方法或不同的方法来编写类了。鉴于这是一个控制器,并且本质上它们将堆栈的不同部分粘合在一起,我会在堆栈的更远的地方创建您的沙箱。具体来说,我会使用这样的方法:
https://github.com/PolishSymfonyCommunity/SymfonyMockerContainer
https://github.com/PolishSymfonyCommunity/SymfonyMockerContainer
Worked great for me :)
对我很有用:)

