在SF3.4及更高版本中运行Symfony DIC烟雾测试
发布时间:2020-12-13 16:09:50 所属栏目:PHP教程 来源:网络整理
导读:从DI容器中获取服务是我的测试套件中烟雾测试的一个组成部分.例如,以下测试确保在容器中注册的服务的构造没有问题,并且这些服务不需要花费太多时间来构建. private const DEFAULT_TRESHOLD = 30;public function testServicesLoadInTime(){ $client = static
从DI容器中获取服务是我的测试套件中烟雾测试的一个组成部分.例如,以下测试确保在容器中注册的服务的构造没有问题,并且这些服务不需要花费太多时间来构建.
private const DEFAULT_TRESHOLD = 30; public function testServicesLoadInTime() { $client = static::createClient(); /** * Add serviceid as key,possible values: * - false: Skip test for this service * - integer value: Custom responsetime */ $customCriteria = [ // See: https://github.com/symfony/monolog-bundle/issues/192 'monolog.activation_strategy.not_found' => false,'monolog.handler.fingers_crossed.error_level_activation_strategy' => false,// Should not be used directly (Factories will inject other parameters) 'liip_imagine.binary.loader.prototype.filesystem' => false,// Services that are allowed to load longer (Only for CLI tasks like workers) 'assetic.asset_manager' => 1000,]; foreach ($client->getContainer()->getServiceIds() as $id) { if (isset($customCriteria[$id]) && $customCriteria[$id] === false) { continue; } try { $startedAt = microtime(true); $service = $client->getContainer()->get($id); $elapsed = (microtime(true) - $startedAt) * 1000; $this->assertNotNull($service); $treshold = $customCriteria[$id] ?? self::DEFAULT_TRESHOLD; $this->assertLessThan($treshold,$elapsed,sprintf( 'Service %s loaded in %d ms which is more than the %d ms threshold',$id,$treshold )); } catch (InactiveScopeException $e) { // Noop } catch (Throwable $ex) { $this->fail(sprintf("Fetching service %s failed: %s",$ex->getMessage())); } } } 然而. Symfony的第4版将生成services private by default.当服务尚未标记为public时,使用get()方法从服务容器获取服务时,即将发布的版本3.4将触发弃用警告. 这让我想知道是否有办法让这个冒烟测试运行而不创建一个公共服务,它将所有服务作为构造函数参数,当然容器中的近1000个服务当然不是一个可行的选择. 解决方法
这种方法
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进行测试等). 那么你所有的测试都会按预期继续工作! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |