Как получить доступ к приватному сервису в тестах phpunit Symfony 3.4?

Я хочу протестировать службу рассылки почты. Я создал модульный тест, но у меня есть предупреждение об устаревании, и я хочу знать, как его использовать. В моей функции 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

Я думаю, что лучше всего использовать DI в вашем случае. Взгляните на это: symfony.com/doc/current/components/dependency_injection.html

Gabriel Deschamps 20.04.2018 13:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
3
1
2 267
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Сервисы были закрыты по умолчанию в Symfony 3.4.

Symfony 4.1

Начиная с Symfony 4.1 все частные сервисы доступны в тестовой среде через специальный тестовый контейнер:

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

Symfony 3.4 и 4.0

Один из способов решить эту проблему в Symfony 3.4 и 4.0 - зарегистрировать локатор сервисов в тестовой среде, который будет предоставлять частные сервисы, к которым вам нужен доступ, в тестах.

Другой путь - это просто создание общедоступного псевдонима для каждой частной службы, к которой вам нужен доступ в тестах.

Например:

# 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');

Спасибо за полный ответ, это очень помогло :)

eldiablo62 23.04.2018 16:06

Это подход со всеми его плюсами и минусами описано в этом посте с примерами кода.


Нет необходимости расширять и поддерживать лишние строки конфигов для тестов. В них не должно быть public: true:

Лучшее решение для доступа к частным сервисам - добавить Compiler Pass, который делает все сервисы общедоступными для тестирования.

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

Но, конечно, лучше использовать собственный класс, который соответствует вашим потребностям (вы можете использовать Behat для тестов и т. д.).

Тогда все ваши тесты будут работать должным образом!

Дайте мне знать, как это работает для вас.

Не работает с symfony 3.4 и twig: Неустранимая ошибка: служба templating.loader.cache зависит от несуществующей службы templating.loader.wrapped. в C: \ www \ vendor \ symfony \ symfony \ src \ Symfony \ Component \ Dependen‌ cyInjection \ Compiler‌ \ CheckExceptionOnInv‌ alidReferenceBehavio‌ rPass.php: 31

Alex83690 04.04.2019 17:15

Я понимаю. В конце концов, я использую public: true для решения всех этих проблем.

Tomas Votruba 04.04.2019 18:03

Другие вопросы по теме