net*_*key 9 git phpunit bundle symfony composer-php
当我们现在开始在几个项目中使用Symfony 2时,我们发现在我们的项目中可以分享相当多的代码.因此,我们开始将功能提取到Symfony 2包中,以便在我们的项目之间共享它们.
虽然我们基本上已经开始工作了,但仍然有很多问题不容易进行,但特别是在测试共享捆绑时.
我们提取的第一个小包包含一个Doctrine Entity,一个kernel.event_listener被自动注入客户端项目的DI容器,一个注释,另一个服务和几个命令.基本思想是客户端项目可以使用我们的注释来注释其控制器,event_listener将拦截对注释控制器的请求,并在最终调用控制器之前执行一些额外的逻辑(涉及教义实体).这些命令用于管理doctrine实体的数据库条目.
到目前为止,一切都完全符合我们的预期,但我们正在努力解决捆绑的可测性问题.首先,保存包的Git存储库不包含完整的Symfony2项目.这样做有点矫枉过正,因为我们只在这里构建一个捆绑包,而不是整个应用程序,对吧?
但是我们如何测试事件监听器呢?我们如何测试它被注入DI容器?我们需要一个测试控制器,它将使用我们的特殊注释进行注释,因此我们可以测试我们的事件监听器是否正确捕获它.该控制器必须在测试时才可用,并且绝不能出现在任何客户端应用程序中.
我们如何测试命令?我们需要模仿学说背后的数据库.当我们尝试在一个简单引导的phpunit测试中执行命令时/vendor/autoload.php,当然我们得到:
致命错误:在第3行的/.../vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php中调用未定义的方法Symfony\Component\Console\Application :: getKernel()
所以感觉就像我们最终需要在我们的bundle的存储库中需要一个完整的Symfony2项目才能引导整个框架以最终测试我们的组件.当我查看开源Symfony2软件包时,我发现没有将整个框架检入他们的Git存储库,所以这仍然感觉不对.
我错过了什么?是否有关于Bundle-Only/Applicationless捆绑开发的文档我缺少?
我在这里找到了一个命令测试解决方案:http://www.ricardclau.com/2013/02/testing-symfony2-commands-mocking-the-di-container-with-mockery/
事实证明,错误来自于ContainerAwareCommand尝试创建一个新容器,这显然不适用于裸测试环境.我通过模拟容器并手动将其注入Command中解决了这个问题,如下所示:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我猜控制器测试必须以类似的,模拟重的方式工作.当我找到解决方案时,我会在这里发布一个完整的答案......
这个问题很老了,但我只是偶然发现的。
捆绑包是 Symfony 共享整个库(包括库)的特定方式。它们各自的依赖注入容器配置。
因此,捆绑包依赖于 Symfony 内核,如果一个捆绑包依赖于另一个捆绑包,则会创建严重的依赖关系,这会有效地阻止单元测试:要测试捆绑包 A 中的单元(类),您需要捆绑包 B 加上 Symfony 内核。
您仍然可以进行测试,但生成的测试是验收/集成测试,而不是单元测试。正如您已经注意到的那样,这些不适合测试驱动开发,缓慢且脆弱。
更新
我刚刚写了一篇关于此的博客文章: https://lastzero.net/2015/11/dependent-symfony-2-bundles-and-testability/