<?php
declare(strict_types=1);
namespace GNexus\Synapse\Tests;
use GNexus\Synapse\Exception\TransportException;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Мини PSR-18 fake без внешних мок-пакетов: очередь/функция
* «запрос → ответ» + журнал отправленных запросов.
*/
final class FakeHttpClient implements ClientInterface
{
/** @var list<RequestInterface> */
public array $requests = [];
/** @var \Closure(RequestInterface): \Psr\Http\Message\ResponseInterface */
private \Closure $handler;
/** @param callable(RequestInterface): \Psr\Http\Message\ResponseInterface $handler */
public function __construct(callable $handler)
{
$this->handler = \Closure::fromCallable($handler);
}
public function sendRequest(RequestInterface $request): ResponseInterface
{
$this->requests[] = $request;
return ($this->handler)($request);
}
/** Фейк-клиент, бросающий транспортную ошибку PSR-18. */
public static function failing(\Throwable $ex): self
{
return new self(static function () use ($ex): never {
throw $ex;
});
}
}
/** Транспортная ошибка, как её бросают реальные PSR-18 клиенты (Guzzle). */
final class FakeNetworkException extends \RuntimeException implements \Psr\Http\Client\NetworkExceptionInterface
{
public function __construct(string $message, private readonly RequestInterface $request)
{
parent::__construct($message);
}
public function getRequest(): RequestInterface
{
return $this->request;
}
}
/** PSR-17 фейк: строит guzzlehttp/psr7 запросы/стримы (dev-зависимость). */
final class FakePsr17
{
public static function requestFactory(): \Psr\Http\Message\RequestFactoryInterface
{
return new \GuzzleHttp\Psr7\HttpFactory();
}
public static function streamFactory(): \Psr\Http\Message\StreamFactoryInterface
{
return new \GuzzleHttp\Psr7\HttpFactory();
}
}