测试流式响应

apo*_*fos 7 php phpunit laravel

我有以下路线:

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

为了简单起见,我们假设它是一个简单的回声响应。实际上,这是一个非常大的文件。两种情况下的结果都是一样的。

现在我想测试这条路线,看看我是否确实可以看到那个 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
}
Run Code Online (Sandbox Code Playgroud)

我进一步检查了它,这似乎是因为 (a) 响应被包裹 a TestResponse(b) 响应内容从不流式传输和 (c) 即使响应内容将通过$response->baseResponse->sendContent()实际内容强制流式传输被回显而不是被实际捕获TestResponse

此外调用$response->getContent()不起作用,因为它似乎直接调用StreamedResponse::getContent()硬编码的 return false。

我使用以下方法取得了一些有限的成功:

ob_start();
$response->sendContent();
$result = ob_get_clean();
Run Code Online (Sandbox Code Playgroud)

然而,这在单元测试中看起来是一件非常草率的事情。

有没有其他人遇到过这种情况?是否可以测试流式响应的内容?

apo*_*fos 5

这不是一个好的解决方案,更像是一种黑客行为,但如果其他人遇到此问题,您可以执行以下操作:

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
}
Run Code Online (Sandbox Code Playgroud)