У меня есть решение сделать сервис общедоступным. В сервисах.yml
test_phpdocxService:
alias: App\Service\PhpDocxService
public: true
Я пытаюсь получить доступ к сервису:
$container = self::$container;
$phpDocxService = $container->get('test_phpdocxService');
$this->filename = $phpDocxService->generateDocxDocument('docx/aaa.html.twig', $data);
Но я нахожу это не таким приятным. Есть ли другой способ сделать это?
Нет, это не работает в Symfony 4.2.
Попробуйте обновить свой вопрос небольшим количеством тестового кода. Сделайте это как можно проще, просто покажите, как вы пытаетесь получить доступ к службе документации.
В порядке. Я сделал это.
Обычно я ценю краткость в вопросе. Необходимость просматривать сотни строк кода утомительна, но в данном случае, я думаю, нам нужно чуть больше. Скопируйте/вставьте WebTestCase в связанный пример, а затем измените имя службы. Вы получаете сообщение об ошибке «служба не найдена»?
Я получаю сообщение: Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException : служба или псевдоним test_phpdocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей.
Используя подход в связанной статье, вы должны запрашивать «App\Service\PhpDocxService», а не «test_phpdocxService».
У меня также не работает Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException : служба или псевдоним App\Service\PhpDocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей. я делаю $phpDocxService = $container->get(\App\Service\PhpDocxService::class);






автопроводка существует начиная с Symfony 3.4, но в версии 4.x он активирован по умолчанию.
Итак, весь ваш класс внутри каталога /src является общедоступным и настроен как службы.
Перейдите к /config/services.yaml, вы найдете этот код:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
Это означает, что ваш файл /src/Сервисы/PhpDocxService.php может вызываться Приложение/Сервисы/PhpDocxService.
Решение, которое вы нашли, - вызвать в службу $this->getContainer()->get('test_phpdocxService');.
Да, но я думаю, что это плохое решение - определять псевдонимы в services.yml только для тестов. Есть ли способ лучше?
Вам нужно создать в config/config_test.yml и объявить, что сервис является общедоступным и другие настройки для тестов там.
Этот подход вы можете использовать в symfony 3/4.
Вы можете прочитать учебник здесь: https://symfonycasts.com/screencast/phpunit/integration-tests
О Функция простого тестирования Symfony 4.1, пожалуйста, прочитайте пост @Cerad
ВЫ НЕ! :)
Вместо этого вы используете новый Более простое тестирование сервиса, реализованный в Symfony 4.1.
При этом тесты на основе WebTestCase и KernelTestCase теперь обращаются к специальному контейнеру через свойство static::$container, позволяющее получать неудаленные приватные сервисы.
А это значит, что приватные сервисы автоматически становятся общедоступными в тестах, если вы используете этот контейнер.
Просто сделайте что-то вроде:
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class SomeClassToTest extends WebTestCase
{
public function getService(string $service)
{
self::bootKernel();
$container = self::$kernel->getContainer();
$container = self::$container;
return self::$container->get($service);
}
public function tesSomething()
{
$imageProcessor = $this->getService('app.some.service');
}
И теперь вы можете получить частную службу app.some.service в средах тестирования.
Конечно да O.o Я использую его в своих проектах и использую Symfony 4.2
Могу подтвердить, что это тоже работает. Только будьте осторожны, чтобы не загрузить ядро дважды.
Хорошо. Итак, есть проблема о тестировании приватных сервисов, которые нигде не используются в вашем приложении. Он все еще открыт и обсуждается, но, по сути, на данный момент вам нужно указать тип вашего частного сервиса где-то в вашем приложении, прежде чем вы сможете получить к нему доступ в тесте.
Используя новую установку 4.4.2:
# src/Service/PhpDocxService.php
namespace App\Service;
class PhpDocxService
{
public function sayHello()
{
return 'hello';
}
}
# src/Controller/MyController.php
namespace App\Controller;
use App\Service\PhpDocxService;
class MyController
{
#****** This is the secret ******
public function __construct(PhpDocxService $phpDocxService)
{
}
}
# src/tests/MyTest.php
namespace App\Tests;
use App\Service\PhpDocxService;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class MyTest extends WebTestCase
{
public function testServiceFound()
{
self::bootKernel();
// gets the special container that allows fetching private services
$container = self::$container;
$phpDocxService = $container->get(PhpDocxService::class);
$this->assertEquals('hello',$phpDocxService->sayHello());
}
}
Введите свой сервис в конструкторе контроллера, и все будет работать как положено.
Услуга находится в использовании. ` общедоступная функция testPhpdocx(PhpDocxService $phpDocxService) { }
@ olek07 Не уверен, что ты имеешь в виду. Вы не можете внедрять службы в методы тестирования. Еще нужно вытащить их из контейнера. Вам просто нужно внедрить его куда-нибудь в ваше приложение, чтобы он не был удален как неиспользуемый при компиляции контейнера.
Да, он уже внедрен в действие testPhpdocx. Это действие является обычным действием, оно не имеет ничего общего с модульным тестом, несмотря на префиксный тест.
Это не работает также в конструкторе Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException : служба или псевдоним App\Service\PhpDocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей.
Я думаю, моя ошибка была в том, что я забыл self::bootKernel();
@ olek07 Я предполагаю, что к настоящему моменту вы уже очень расстроены всем этим. Вероятно, перепробовал много подходов. Сделайте перерыв. Затем вернитесь и создайте новый проект. Добавьте три файла, которые я разместил выше, и убедитесь, что они работают должным образом. Что будет. Затем, возможно, вернитесь и выясните, почему это не работает в вашем текущем проекте. И да, загрузка ядра очень важна.
Он работает без внедрения сервиса в конструктор. В чем секрет сейчас?
@ olek07 Только что провел быстрый тест, и кажется, что инъекция действия работает. Прохладный. В моем случае отсутствие инъекций в любом месте приводит к тому, что служба не найдена.
Но не с имитацией службы $container->set(\App\Service\PhpDocxService::class, $someService); генерирует сообщение Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException : служба или псевдоним App\Service\PhpDocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей.
Я не вижу ничего о насмешках над сервисом в вашем вопросе. Совершенно другая проблема, и ее лучше избегать, если это возможно.
Я думал, что с помощью этого решения можно издеваться над частными сервисами.
Спасибо, @Cerad, за расшифровку того, что означает «неиспользованный сервис»!
Не рекомендуется добавлять аргумент конструктора, который не будет использоваться нигде в классе, только для включения модульного тестирования. Лучше использовать тестовый конфигурационный файл, где нужный сервис выложен в общий доступ.
более простое сервисное тестирование у вас не работает?