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?
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
}
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.
Laravel doc for TestResponse
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With