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




Сервисы были закрыты по умолчанию в 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');
Спасибо за полный ответ, это очень помогло :)
Это подход со всеми его плюсами и минусами описано в этом посте с примерами кода.
Нет необходимости расширять и поддерживать лишние строки конфигов для тестов. В них не должно быть public: true:
Лучшее решение для доступа к частным сервисам - добавить Compiler Pass, который делает все сервисы общедоступными для тестирования.
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());
}
}
Где 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
Я понимаю. В конце концов, я использую public: true для решения всех этих проблем.
Я думаю, что лучше всего использовать DI в вашем случае. Взгляните на это: symfony.com/doc/current/components/dependency_injection.html