使用PHPUnit测试Symfony3中的服务/服务容器的优雅方法

前端之家收集整理的这篇文章主要介绍了使用PHPUnit测试Symfony3中的服务/服务容器的优雅方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我最近在学习Symfony 3框架和依赖注入.

我希望您帮助我解决我对使用PHPUnit在Symfony 3中测试服务的方法的疑虑.我有一些担心如何正确地做到这一点.

让我们举一个Service类的例子:

  1. // src/AppBundle/Services/MathService.PHP
  2. namespace AppBundle\Services;
  3.  
  4. class MathService
  5. {
  6. public function subtract($a,$b)
  7. {
  8. return $a - $b;
  9. }
  10. }

我看到通常Symfony中的UnitTest类测试控制器.

但是我可以测试像服务这样的独立类(例如包含业务逻辑)而不是控制器?

我知道至少有两种方法可以做到:

1.创建一个测试类,它扩展了PHPUnit_Framework_TestCase,并在此测试类中的某些方法或构造函数中创建了Service对象(与Symfony docs about testing中的内容完全相同)

  1. // tests/AppBundle/Services/MathTest.PHP
  2. namespace Tests\AppBundle\Services;
  3.  
  4. use AppBundle\Services\MathService;
  5.  
  6. class MathTest extends \PHPUnit_Framework_TestCase
  7. {
  8. protected $math;
  9.  
  10. public function __construct() {
  11. $this->math = new MathService();
  12. }
  13.  
  14. public function testSubtract()
  15. {
  16. $result = $this->math->subtract(5,3);
  17. $this->assertEquals(2,$result);
  18. }
  19. }

2.使用依赖注入将我们的​​Service类作为服务容器.然后创建一个Test Class,它扩展了KernelTestCase以访问内核.它将使我们能够使用来自内核的Container注入我们的服务(基于Symfony docs about testing Doctrine).

服务容器的配置:

  1. # app/config/services.yml
  2. services:
  3. app.math:
  4. class: AppBundle\Services\MathService

现在我们的测试类看起来像:

  1. // tests/AppBundle/Services/MathTest.PHP
  2. namespace Tests\AppBundle\Services;
  3.  
  4. use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
  5.  
  6. class MathTest extends KernelTestCase
  7. {
  8. private $math;
  9.  
  10. protected function setUp()
  11. {
  12. self::bootKernel();
  13.  
  14. $this->math = static::$kernel
  15. ->getContainer()
  16. ->get('app.math');
  17. }
  18.  
  19. public function testSubtract()
  20. {
  21. $result = $this->math->subtract(5,$result);
  22. }
  23. }

我们选择这种方式有好处.

首先,我们可以通过依赖注入访问控制器和测试中的服务容器.

其次 – 如果将来我们想要更改Service类的位置或更改类的名称 – 与1. case相比 – 我们可以避免更改许多文件,因为我们将至少在services.yml文件中更改路径/名称.

我的问题:

是否有其他方法可以在Symfony 3中测试Service类?哪种方式更好,应该使用?

使用棘手的Symfony 3.4 / 4.0解决方案更新2018年.

这种方法with all its pros/cons is described in this post with code examples.

访问私有服务的最佳解决方案是添加一个编译器通行证,使所有服务公开以进行测试.

1.更新内核

  1. use Symfony\Component\HttpKernel\Kernel;
  2. +use Symplify\PackageBuilder\DependencyInjection\CompilerPass\PublicForTestsCompilerPass;
  3.  
  4. final class AppKernel extends Kernel
  5. {
  6. protected function build(ContainerBuilder $containerBuilder): void
  7. {
  8. $containerBuilder->addCompilerPass('...');
  9. + $containerBuilder->addCompilerPass(new PublicForTestsCompilerPass());
  10. }
  11. }

2.需要或创建自己的编译器通行证

PublicForTestsCompilerPass的位置如下:

  1. use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  2. use Symfony\Component\DependencyInjection\ContainerBuilder;
  3.  
  4. final class PublicForTestsCompilerPass implements CompilerPassInterface
  5. {
  6. public function process(ContainerBuilder $containerBuilder): void
  7. {
  8. if (! $this->isPHPUnit()) {
  9. return;
  10. }
  11.  
  12. foreach ($containerBuilder->getDefinitions() as $definition) {
  13. $definition->setPublic(true);
  14. }
  15.  
  16. foreach ($containerBuilder->getAliases() as $definition) {
  17. $definition->setPublic(true);
  18. }
  19. }
  20.  
  21. private function isPHPUnit(): bool
  22. {
  23. // defined by PHPUnit
  24. return defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__');
  25. }
  26. }

要使用此类,只需通过以下方式添加包:

  1. composer require symplify/package-builder

但是,当然,更好的方法是使用自己的类,满足您的需求(您可以迁移Behat进行测试等).

那么你所有的测试都将按预期继续工作!

猜你在找的PHP相关文章