如何在Symfony 3.4 phpunit测试中访问私有服务?

时间:2018-04-20 09:08:01

标签: symfony phpunit

我想测试发送邮件的服务。我已经创建了一个单元测试,但我有一些弃用警告,我想知道它的用处。 在我的setUp()函数中,我得到了像这样的服务

    $this->container = self::$kernel->getContainer();
    $this->swiftMailer = $this->container->get('swiftmailer.mailer');

但我有这个消息

The "swiftmailer.mailer" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.

最好的做法是什么? 我对security.authentication.manager

有相同的信息

2 个答案:

答案 0 :(得分:1)

此方法with all its pros/cons is described in this post with code examples

无需为测试扩展和维护额外的配置线。其中应该没有public: true

enter image description here

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

1。更新内核

 use Symfony\Component\HttpKernel\Kernel;
+use Symplify\PackageBuilder\DependencyInjection\CompilerPass\PublicForTestsCompilerPass;

 final class AppKernel extends Kernel
 {
     protected function build(ContainerBuilder $containerBuilder): void
     {
         $containerBuilder->addCompilerPass('...');
+        $containerBuilder->addCompilerPass(new PublicForTestsCompilerPass());
     }
 }

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

PublicForTestsCompilerPass的样子:

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

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

但是,当然,更好的方法是使用自己的类,满足您的需求(您可能需要测试等)。

然后您的所有测试都会按预期继续工作!

请告诉我,这对您有何帮助。

答案 1 :(得分:0)

Symfony 3.4中的服务were made private by default

Symfony 4.1

从Symfony 4.1 all private services are made available in test environment开始,通过一个特殊的测试容器:

class FooTest extends KernelTestCase
{
    static::bootKernel();
    $this->swiftmailer = static::$container->get('swiftmailer.mailer');
}

Symfony 3.4和4.0

在Symfony 3.4和4.0中解决它的一种方法是在测试环境中注册服务定位器,这将暴露您需要在测试中访问的私有服务。

Another way只是为您需要在测试中访问的每个私有服务创建一个公共别名。

例如:

# app/config/config_test.yml
services:
    test_alias.swiftmailer.mailer:
        alias: '@swiftmailer.mailer'
        public: true

在您的测试中,您现在可以通过公共别名test_alias.swiftmailer.mailer访问您的私人服务:

$this->container = self::$kernel->getContainer();
$this->swiftMailer = $this->container->get('test_alias.swiftmailer.mailer');