Symfony 5: Проводные аргументы метода контроллера вручную

#symfony #testing #controller #symfony5

Вопрос:

Я пытаюсь издеваться над сервисом, чтобы протестировать один из методов моего контроллера:

 class ExampleController extends AbstractController
{
     /**
     * @Route("/example", name="app_example", methods={"POST"})
     */
     public function exampleMethod(Request $request, IService $service) {}
}
 

В тестовой среде я хотел бы подключить макет службы, но я не могу узнать, как вручную подключать аргументы контроллера (в отличие от аргументов службы). Это то, что я делал до сих пор, но это не работает:

 //services_test.yaml

  AppControllerExampleController:
    arguments:
      $service: '@AppServiceServiceMock'
 

Я получаю следующую ошибку:

 Invalid service "AppControllerExampleController": class has no constructor.
 

Комментарии:

1. arguments директива предоставляет способ введения зависимости через конструктор, поэтому, если вы ее используете, вам нужно добавить конструктор, как указано @user9245255. Не могли бы вы добавить коды модульного теста, пожалуйста.

2. Вы пытаетесь провести какой-то интеграционный тест? Если это так, то вы просто определите свою службу в тестовой среде. Код Symfony, который фактически вводит аргументы в методы действий, не является чем-то, что вы можете изменить. По крайней мере, нелегко.

Ответ №1:

Попробуйте добавить конструктор в свой контроллер и сделать IService его параметром

Комментарии:

1. Как именно добавление его в конструктор позволит внедрить другую реализацию в тестовую среду?

Ответ №2:

Ваш контроллер (src/Controller/ExampleController.php):

 use AppServiceIService

class ExampleController extends AbstractController
{
    /**
    * @Route("/example", name="app_example", methods={"POST"})
    */
    public function exampleMethod(Request $request, IService $service)
    {
       dd($service->testing());
    }
}
 

Создайте свой пустой макет службы (src/Service/IService.php):

 namespace AppService;

class IService
{
    public function __construct()
    {
    }
    
    public function testing(): string
    {
        return 'hello';
    }
}
 

Symfony автоматически введет ваш сервис, вам не нужно добавлять его в свои сервисы.файл yaml. Однако не забудьте добавить use AppServiceIService свой контроллер.

Комментарии:

1. Хммм. Вопрос в том, как внедрить другую реализацию IService в тестовую среду. В первую очередь не о том, как создать сервис.

2. @Cerad извините, тогда я неправильно понял вопрос. Это для модульного тестирования? Как бы вы это сделали?

3. Сам вопрос не очень ясен, но я думаю, что это интеграционный тест, и в этом случае вы бы определили тестовую реализацию IService в services_test. yaml, который переопределит реализацию по умолчанию. С другой стороны, в вопросе используется термин «макет», который обычно ассоциируется с модульным тестированием. Я думаю, нам просто нужно будет посмотреть, решит ли оригинальный плакат вернуться или нет.

4. Да, это интеграционный тест. Внедряемая служба полагается на внешние библиотеки и подключается к другим облачным сервисам, что замедляет тесты, а также заставляет меня проводить очень хрупкие тесты. Возможно, я неправильно использовал термин «макет», но, по сути, я хочу этого: предоставить поддельную реализацию, чтобы я проверял свою собственную логику, а не эту внешнюю службу.