Внедрение фиктивных объектов с помощью PHP-DI для тестирования контроллеров с помощью PHPUnit

Я реорганизовал некоторые из своих контроллеров, чтобы использовать внедрение зависимостей через внедрение свойств как рекомендовано в "лучших практиках":

final class ZebraController extends Controller
{
    /**
     * @Inject
     * @var AnimalClientInterface
     */
    private $animalsRestClient;

    public function fetchAllZebras(ServerRequestInterface $req): ResponseInterface {
        // ...
    }
}

Моя конфигурация PHP-DI настроена на внедрение экземпляра объекта AnimalClient для AnimalClientInterface, что хорошо в коде реализации, поскольку существует только 1 настоящий AnimalClient.

В моем модульном тесте мне нужно внедрить MockZebraClient в это свойство. Я не могу просто настроить его, как я делаю это для AnimalClient, потому что другие классы могут быть аннотированы аналогичным образом, но им нужен, например, MockTigerClient для тестирования.

Это мой модульный тест:

class ZebraControllerTest extends TestCase
{
    /** @var ZebraController */
    protected $object;

    public function testFetchAllZebras(): void {
        // assertions here
    }
}

Я думаю, что использование Метод injectOn — правильный способ решить эту проблему, но я не знаю, как настроить контейнер, чтобы выбрать правильный фиктивный объект для правильного теста.

Внедрение конструктора невозможно из-за устаревшей структуры кода. Все контроллеры в приложении должны быть реорганизованы для использования DI, чтобы изменить конструктор Controller.

Не знаком с PHP-DI, но вы всегда можете добавить конструктор и вызвать его в своих тестах.

John V. 21.01.2019 07:08

@ДжонВ. К сожалению, я не могу изменить сигнатуру метода конструктора Controller из-за устаревшей структуры кода. Переопределение его в дочернем классе для добавления дополнительных параметров также невозможно, пока все контроллеры в кодовой базе не будут реорганизованы для использования DI.

rink.attendant.6 21.01.2019 07:43
Стоит ли изучать 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 и хотите разрабатывать...
2
2
643
1

Ответы 1

Возможно, есть конкретный ответ PHP-DI, но я с ним не знаком. Также кажется, что определение конструктора не разрешено в вашем случае. Учитывая это, вы можете использовать статический конструктор для тестирования, который позволяет получить доступ к настройке внутреннего состояния:

<?php
class A {
    private $b;

    public static function construct($b) {
        $a = new A();
        $a->b = $b;
        return $a;
    }
}

class B {

}

$a = A::construct(new B());
var_dump($a);

Возвращает:

object(A)#2 (1) { ["b":"A":private]=> object(B)#1 (0) { } }

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