Тестируйте свой код без сети

PHP

Используйте тестовый дублёр, который поставляется с SDK, чтобы ставить в очередь ответы API и проверять запросы, которые отправил ваш код.

4 мин чтения

SDK поставляется с тестовым дублёром своего HTTP-клиента. Тест ставит в очередь ответы, которые дал бы API, запускает ваш код на настоящем SDK и читает обратно запросы, которые SDK отправил. Ни один запрос не покидает процесс, а ключом служит любой непустой текст.

Дублёр — FakeHttpClient, в пространстве имён Slen\Sdk\Testing: клиент PSR-18.

Написать тест

1. Поставьте ответ в очередь

Создайте дублёр и поставьте в очередь ответ API: статус и тело, как их отправляет API. Тело успешного ответа обёрнуто в data.

PHP
use Slen\Sdk\Testing\FakeHttpClient;

$http = (new FakeHttpClient())->pushJson(200, ['data' => [
    'execution_id' => '74438200973594700',
    'status' => 'completed',
    'operation' => 'generate_email',
    'output' => ['content' => 'Hi Ada, just checking in on the proposal I sent last week.'],
    'error' => null,
    'error_code' => null,
    'error_message' => null,
    'cost' => ['estimated' => '0.00412500', 'actual' => null],
    'cache' => ['hit' => false, 'cached_at' => null],
    'replayed' => false,
    'waiting_on' => null,
    'trace_url' => '/v1/executions/74438200973594700',
]]);

2. Дайте дублёр SDK

SDK — настоящий. Заменён только его HTTP-клиент, поэтому тест выполняет тот же код, что и ваше приложение.

PHP
use Slen\Sdk\SlenConfig;
use Slen\Sdk\SlenSdk;

$slen = SlenSdk::create(new SlenConfig(apiKey: 'key-for-tests', httpClient: $http));

Дублёр — это httpClient конфигурации.

3. Запустите свой код

PHP
use Slen\Sdk\Modules\Operations\Options\ExecuteOptions;

$execution = $slen->operations()->execute(
    'generate_email',
    ['messages' => [['role' => 'user', 'content' => 'Write a short follow-up email.']]],
    new ExecuteOptions(idempotencyKey: 'order-42:email'),
);

4. Проверьте, что ушло

Дублёр записывает каждый запрос: метод, адрес, заголовки и тело.

PHP
$sent = $http->lastRequest();

echo $execution->status->value, PHP_EOL;
echo $sent->getMethod(), ' ', $sent->getUri(), PHP_EOL;
echo $sent->getHeaderLine('Idempotency-Key'), PHP_EOL;
echo json_decode((string) $sent->getBody(), true)['operation'], PHP_EOL;

lastRequest() возвращает последний запрос, а requests() — все, как запросы PSR-7.

Ответы выдаются в порядке очереди

Каждый запрос берёт следующий ответ из очереди. Ставьте в очередь по ответу на каждый запрос, который делает ваш код.

Дублёр строгий. Запрос, для которого в очереди нет ответа, проваливает тест с LogicException, и запрос всё равно записывается. Дублёр, который прощал бы лишний запрос, скрыл бы ту ошибку, ради которой он нужен, — вызов, отправленный дважды.

SDK отправляет запрос ещё раз после 429, 503 или когда ответа не было — столько раз, сколько говорит retries, — Повторы и таймауты. Тест такого ответа ставит в очередь по ответу на каждую попытку или задаёт retries, равное 0, — всему SDK или в опциях одного вызова.

Протестировать ошибку

Поставьте ошибку в очередь так же: её статус и конверт ошибки API. SDK выбрасывает ту ошибку, которую выбросил бы на настоящий ответ. Конверт описывает статья Обзор.

404 Not Found
{
  "error": {
    "code": "flow_not_found",
    "message": "No flow is bound to operation \"generate_email\"",
    "request_id": "0d3c1b9e-5a47-4f0e-9a36-2f6c8d1e7b42"
  }
}

pushException() ставит в очередь исключение HTTP-клиента вместо ответа. Сетевое исключение PSR-18 изображает запрос, который остался без ответа, и SDK после него отправляет запрос ещё раз: поставьте по одному на каждую попытку, и SDK выбросит ConnectionException после последней.

Протестировать спаны

RecordingSpanRecorder, переданный в конфигурацию как spanRecorder, держит спаны теста: spans() возвращает их все, а last() — последний, — Спаны.

Что читать дальше