【发布时间】:2014-08-06 17:47:37
【问题描述】:
当我们现在开始在几个项目中使用 Symfony 2 时,我们发现我们可以在我们的项目之间共享相当多的代码。所以我们开始将特性提取到 Symfony 2 包中,以便在我们的项目之间共享它们。
虽然我们基本上可以解决问题,但仍有不少问题难以通过 Google 搜索,尤其是在测试共享捆绑包时。
我们提取的第一个小包包含一个 Doctrine 实体、一个自动注入到客户端项目的 DI 容器中的 kernel.event_listener、一个注释、另一个服务和几个命令。基本思想是客户端项目可以用我们的注解来注解它的控制器,event_listener 会在最终调用控制器之前拦截对被注解的控制器的请求并执行一些额外的逻辑(涉及教义实体)。这些命令旨在管理学说实体的数据库条目。
到目前为止,一切都完全按照我们的预期工作,但我们正在努力解决捆绑包的可测试性问题。首先,包含捆绑包的 Git 存储库不包含完整的 Symfony2 项目。这将是矫枉过正,因为我们只是在这里构建一个包,而不是一个完整的应用程序,对吧?
但是我们如何测试事件监听器呢?我们如何测试它是否被注入到 DI 容器中?我们需要一个测试控制器,该控制器将使用我们的特殊注释进行注释,因此我们可以测试我们的事件侦听器是否正确捕获它。该控制器必须仅在测试时可用,并且不得出现在任何客户端应用程序中。
我们如何测试命令?我们需要模拟学说背后的数据库。当我们尝试在简单地用/vendor/autoload.php 引导的 phpunit 测试中执行命令时,我们当然会得到:
致命错误:调用未定义的方法 Symfony\Component\Console\Application::getKernel() 在 /.../vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php 在第 3 行
所以感觉就像我们最终需要在我们的包的存储库中使用一个完整的 Symfony2 项目,以便引导整个框架以便最终能够测试我们的组件。当我查看开源 Symfony2 包时,我发现没有一个将整个框架签入到他们的 Git 存储库中,所以这仍然是错误的。
我错过了什么?我是否缺少有关仅捆绑/无应用程序捆绑开发的文档?
编辑:
我在这里找到了命令测试的解决方案:http://www.ricardclau.com/2013/02/testing-symfony2-commands-mocking-the-di-container-with-mockery/
原来错误来自ContainerAwareCommand 试图创建一个新容器,这显然无法在裸测试环境中工作。我通过模拟容器并将其手动注入命令来解决问题,如下所示:
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class MyCommandTest extends \PHPUnit_Framework_TestCase {
public function testExecute() {
$application = new Application();
$application->add(new MyCommand());
$command = $application->find('my:command');
$command->setContainer($this->getMockContainer()); // <= This avoids ContainerAwareCommand creating a 'real' container in a test env
$commandTester = new CommandTester($command);
$commandTester->execute(array('command' => $command->getName()));
print $commandTester->getDisplay();
$this->assertRegExp('/.../', $commandTester->getDisplay());
}
protected function getMockContainer() {
// Mock the container and everything you'll need here
$mockDoctrine = $this->getMock('Symfony\Bridge\Doctrine\RegistryInterface');
$mockDoctrine->...;
$mockContainer = $this->getMock('Symfony\Component\DependencyInjection\Container');
$mockContainer->expects($this->once())
->method('get')
->with('doctrine')
->willReturn($mockDoctrine);
return $mockContainer;
}
}
我猜控制器测试必须以类似的、大量模拟的方式工作。当我找到它的解决方案时,我会在这里发布一个完整的答案......
【问题讨论】:
-
我不是真正的专家(没有太多时间进行实验和太多工作),但我认为您只需要框架包、控制台、http-kernel 等依赖项的子集即可设置并运行您的测试。
-
也许你的编辑应该是一个答案......无论如何,好的起点。谢谢!
标签: git symfony phpunit bundle composer-php