Инжектирование фиктивных объектов с использованием 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,

1 ответ

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

<?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) {}}

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