Symfony 4.2 Как сделать сервис публичным только для тестов

У меня есть решение сделать сервис общедоступным. В сервисах.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);

Но я нахожу это не таким приятным. Есть ли другой способ сделать это?

более простое сервисное тестирование у вас не работает?

Cerad 01.02.2019 14:02

Нет, это не работает в Symfony 4.2.

olek07 01.02.2019 15:33

Попробуйте обновить свой вопрос небольшим количеством тестового кода. Сделайте это как можно проще, просто покажите, как вы пытаетесь получить доступ к службе документации.

Cerad 01.02.2019 15:36

В порядке. Я сделал это.

olek07 01.02.2019 15:48

Обычно я ценю краткость в вопросе. Необходимость просматривать сотни строк кода утомительна, но в данном случае, я думаю, нам нужно чуть больше. Скопируйте/вставьте WebTestCase в связанный пример, а затем измените имя службы. Вы получаете сообщение об ошибке «служба не найдена»?

Cerad 01.02.2019 15:58

Я получаю сообщение: Symfony\Component\DependencyInjection\Exception\ServiceNotFo‌​undException : служба или псевдоним test_phpdocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей.

olek07 01.02.2019 16:19

Используя подход в связанной статье, вы должны запрашивать «App\Service\PhpDocxService», а не «test_phpdocxService».

Cerad 01.02.2019 16:28

У меня также не работает Symfony\Component\DependencyInjection\Exception\ServiceNotFo‌​undException : служба или псевдоним App\Service\PhpDocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей. я делаю $phpDocxService = $container->get(\App\Service\PhpDocxService::class);

olek07 01.02.2019 16:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
5
8
8 401
4

Ответы 4

автопроводка существует начиная с 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 только для тестов. Есть ли способ лучше?

olek07 01.02.2019 08:55

Вам нужно создать в 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

Eduardo Fernandes 01.02.2019 15:45

Могу подтвердить, что это тоже работает. Только будьте осторожны, чтобы не загрузить ядро ​​дважды.

Dean 14.01.2020 08:40

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

Используя новую установку 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 01.02.2019 22:40

@ olek07 Не уверен, что ты имеешь в виду. Вы не можете внедрять службы в методы тестирования. Еще нужно вытащить их из контейнера. Вам просто нужно внедрить его куда-нибудь в ваше приложение, чтобы он не был удален как неиспользуемый при компиляции контейнера.

Cerad 01.02.2019 22:55

Да, он уже внедрен в действие testPhpdocx. Это действие является обычным действием, оно не имеет ничего общего с модульным тестом, несмотря на префиксный тест.

olek07 01.02.2019 23:02

Это не работает также в конструкторе Symfony\Component\DependencyInjection\Exception\ServiceNotFo‌​undException : служба или псевдоним App\Service\PhpDocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей.

olek07 01.02.2019 23:26

Я думаю, моя ошибка была в том, что я забыл self::bootKernel();

olek07 01.02.2019 23:31

@ olek07 Я предполагаю, что к настоящему моменту вы уже очень расстроены всем этим. Вероятно, перепробовал много подходов. Сделайте перерыв. Затем вернитесь и создайте новый проект. Добавьте три файла, которые я разместил выше, и убедитесь, что они работают должным образом. Что будет. Затем, возможно, вернитесь и выясните, почему это не работает в вашем текущем проекте. И да, загрузка ядра очень важна.

Cerad 01.02.2019 23:31

Он работает без внедрения сервиса в конструктор. В чем секрет сейчас?

olek07 01.02.2019 23:33

@ olek07 Только что провел быстрый тест, и кажется, что инъекция действия работает. Прохладный. В моем случае отсутствие инъекций в любом месте приводит к тому, что служба не найдена.

Cerad 01.02.2019 23:38

Но не с имитацией службы $container->set(\App\Service\PhpDocxService::class, $someService); генерирует сообщение Symfony\Component\DependencyInjection\Exception\ServiceNotFo‌​undException : служба или псевдоним App\Service\PhpDocxService был удален или встроен при компиляции контейнера. Вы должны либо сделать его общедоступным, либо прекратить использовать контейнер напрямую и вместо этого использовать внедрение зависимостей.

olek07 01.02.2019 23:42

Я не вижу ничего о насмешках над сервисом в вашем вопросе. Совершенно другая проблема, и ее лучше избегать, если это возможно.

Cerad 02.02.2019 00:14

Я думал, что с помощью этого решения можно издеваться над частными сервисами.

olek07 02.02.2019 09:42

Спасибо, @Cerad, за расшифровку того, что означает «неиспользованный сервис»!

erop 04.12.2019 00:07

Не рекомендуется добавлять аргумент конструктора, который не будет использоваться нигде в классе, только для включения модульного тестирования. Лучше использовать тестовый конфигурационный файл, где нужный сервис выложен в общий доступ.

René Pöpperl 03.10.2021 18:27

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