使用PHPUnit测试Symfony3中的服务/服务容器的优雅方法
我最近在学习Symfony 3框架和依赖注入.
我希望您帮助我解决我对使用PHPUnit在Symfony 3中测试服务的方法的疑虑.我有一些担心如何正确地做到这一点. 让我们举一个Service类的例子: // src/AppBundle/Services/MathService.php namespace AppBundleServices; class MathService { public function subtract($a,$b) { return $a - $b; } } 我看到通常Symfony中的UnitTest类测试控制器. 但是我可以测试像服务这样的独立类(例如包含业务逻辑)而不是控制器? 我知道至少有两种方法可以做到: 1.创建一个测试类,它扩展了PHPUnit_Framework_TestCase,并在此测试类中的某些方法或构造函数中创建了Service对象(与Symfony docs about testing中的内容完全相同) // tests/AppBundle/Services/MathTest.php namespace TestsAppBundleServices; use AppBundleServicesMathService; class MathTest extends PHPUnit_Framework_TestCase { protected $math; public function __construct() { $this->math = new MathService(); } public function testSubtract() { $result = $this->math->subtract(5,3); $this->assertEquals(2,$result); } } 2.使用依赖注入将我们的??Service类作为服务容器.然后创建一个Test Class,它扩展了KernelTestCase以访问内核.它将使我们能够使用来自内核的Container注入我们的服务(基于Symfony docs about testing Doctrine). 服务容器的配置: # app/config/services.yml services: app.math: class: AppBundleServicesMathService 现在我们的测试类看起来像: // tests/AppBundle/Services/MathTest.php namespace TestsAppBundleServices; use SymfonyBundleFrameworkBundleTestKernelTestCase; class MathTest extends KernelTestCase { private $math; protected function setUp() { self::bootKernel(); $this->math = static::$kernel ->getContainer() ->get('app.math'); } public function testSubtract() { $result = $this->math->subtract(5,$result); } } 我们选择这种方式有好处. 首先,我们可以通过依赖注入访问控制器和测试中的服务容器. 其次 – 如果将来我们想要更改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.更新内核 use SymfonyComponentHttpKernelKernel; +use SymplifyPackageBuilderDependencyInjectionCompilerPassPublicForTestsCompilerPass; final class AppKernel extends Kernel { protected function build(ContainerBuilder $containerBuilder): void { $containerBuilder->addCompilerPass('...'); + $containerBuilder->addCompilerPass(new PublicForTestsCompilerPass()); } } 2.需要或创建自己的编译器通行证 PublicForTestsCompilerPass的位置如下: use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface; use SymfonyComponentDependencyInjectionContainerBuilder; final class PublicForTestsCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $containerBuilder): void { if (! $this->isPHPUnit()) { return; } foreach ($containerBuilder->getDefinitions() as $definition) { $definition->setPublic(true); } foreach ($containerBuilder->getAliases() as $definition) { $definition->setPublic(true); } } private function isPHPUnit(): bool { // defined by PHPUnit return defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__'); } } 要使用此类,只需通过以下方式添加包: composer require symplify/package-builder 但是,当然,更好的方法是使用自己的类,满足您的需求(您可以迁移Behat进行测试等). 那么你所有的测试都将按预期继续工作! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |