Reputation: 40681
I have the following route:
Route::get('echo',function (Request $req) {
return response()->stream(function () use ($req) {
echo json_encode($req->all());
}, 200, [
'Content-Type' => 'application/json'
]);
})->name('echo');
For the sake of simplicity lets assume it's a simple echo response. In reality it's a very large file. The outcome in either case is the same.
Now I want to test this route to see whether I indeed can see that json content so I've tried this:
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
}
I've inspected it a bit further and it appears to be because (a) the response is wrapped around a TestResponse
(b) the response content is never streamed and (c) even if the response content were to be forcibly streamed via $response->baseResponse->sendContent()
the actual content is echoed and not actually captured by the TestResponse
In addition calling $response->getContent()
does not work because it seems to directly call the StreamedResponse::getContent()
which is hard-coded to return false
.
I have managed to have some limited success using:
ob_start();
$response->sendContent();
$result = ob_get_clean();
however this looks like a very sloppy thing to do in a unit test.
Has anyone else encountered this before? Is it possible to test the contents of a streamed response?
Upvotes: 10
Views: 6574
Reputation: 139
A bit late to the party but it may help someone else.
In Laravel you can do $response->streamedContent()
when handling a StreamedResponse
(since 5.8 I believe).
Even tho my debugger told me the streamed content of my response was null
I still got the data out of it.
In my case it was CSV so in my functional tests I've done :
$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...
I used LeagueCSV (bc it was CSV, obviously) but I'm sure you can do the same with Json or other.
Upvotes: 4
Reputation: 40681
This is not a good solution, more of a hack, but if anyone else encounters this issue here's what you can do:
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
}
Upvotes: 6