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