Протестируйте ответ в потоковом режиме

У меня следующий маршрут:

Route::get('echo',function (Request $req) {
    return response()->stream(function () use ($req) {
        echo json_encode($req->all());
    }, 200, [
        'Content-Type' => 'application/json'
    ]);
})->name('echo');

Для простоты предположим, что это простой отклик эха. На самом деле это очень большой файл. Результат в любом случае одинаков.

Теперь я хочу протестировать этот маршрут, чтобы увидеть, действительно ли я вижу этот json-контент, поэтому я попробовал это:

public function testBasicTest()
{

    $response = $this->get(route('echo', [
        "content"=>"some content"
    ]));
    $response->assertSeeText("some content"); //Doesn't work
    $response->assertJson( [
        "content"=>"some content"
    ]); //Neither does this
}

Я проверил его немного дальше, и, похоже, это связано с тем, что (а) ответ обернут вокруг TestResponse (б) содержимое ответа никогда не передается в потоковом режиме и (в) даже если содержимое ответа должно было быть принудительно передано в потоковом режиме через $response->baseResponse->sendContent(), фактическое содержимое отображается эхом, а не захватывается TestResponse

Вдобавок вызов $response->getContent() не работает, потому что кажется, что он напрямую вызывает StreamedResponse::getContent(), который жестко запрограммирован для возврата false.

Мне удалось добиться некоторого ограниченного успеха, используя:

ob_start();
$response->sendContent();
$result = ob_get_clean();

однако это выглядит как очень небрежная вещь в модульном тесте.

Кто-нибудь еще сталкивался с этим раньше? Можно ли проверить содержимое потокового ответа?

Стоит ли изучать 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 и хотите разрабатывать...
7
0
1 944
2

Ответы 2

Это не лучшее решение, это скорее взлом, но если кто-то еще столкнется с этой проблемой, вот что вы можете сделать:

public function testBasicTest()
{

    $response = $this->get(route('echo', [
        "content"=>"some content"
    ]));
    if ($response->baseResponse instanceof StreamedResponse) {
            ob_start();
            $response->sendContent();
            $content = ob_get_clean();
            $response = new TestResponse(
                new Response($content, 
                             $response->baseResponse->getStatusCode(), 
                             $response->baseResponse->headers->all()
                )
            );
    }
    $response->assertSee("some content"); //Works
}

Некоторое время назад возник вопрос: stackoverflow.com/q/15734677/7362396 - и более "чистого" решения тоже не найдено :-(

Tobias K. 17.08.2018 15:02

@TobiasK Я не знал об этом. Мне, наверное, следовало расширить свой поиск до Symfony, а не только до Laravel.

apokryfos 17.08.2018 15:04

Никакой критики на ваш ответ. Я думаю, что вопрос в порядке, поскольку он относится к Laravel, в отличие от другого вопроса. Возможно, не всем понятно, что StreamedResponse является частью Symfony. Просто хотел представить то, что я нашел, в качестве контекста.

Tobias K. 17.08.2018 15:07

@TobiasK Я просто отмечаю, что больше самооценки, ваш комментарий был на самом деле очень полезным.

apokryfos 17.08.2018 15:09

Немного поздно на вечеринку, но это может помочь кому-то другому.

В Laravel вы можете использовать $response->streamedContent() при работе с StreamedResponse (я считаю, что с версии 5.8).

Даже несмотря на то, что мой отладчик сказал мне, что потоковый контент моего ответа был null, я все равно получил данные из него.

В моем случае это был CSV, поэтому в своих функциональных тестах я сделал:

$res = $this->post('api/v1/entity/export', $payload, $header);
$res->assertStatus(200);
$res->assertHeader('Content-Disposition', 'attachment; filename=entity.csv');

$reader = Reader::createFromString($res->streamedContent());
// tests...

Я использовал LeagueCSV (очевидно, это был CSV), но я уверен, что вы можете сделать то же самое с Json или другими.

Документация Laravel для TestResponse

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