Unable to obtain response body in PHPUnit for Slim 4

I’m testing a POST endpoint. In postman everything works.

But PHPUnit always has empty body hence I’m unable to perform necessary assertions.

    public function testDiscountCalculationForVariousDiscountStrategiesIsSuccessfullyInvoked(
        $orderJsonPayloadName,
        $strategyName
    ) {
        $payload = $this->getOrderJsonPayload($orderJsonPayloadName); // json content

        $request = $this
            ->createRequest('POST', '/api/discounts/calculate')
            ->withQueryParams(['strategy' => $strategyName])
            ->withParsedBody($payload);

        $response = $this->app->handle($request);

        $this->assertEquals(200, $response->getStatusCode());

        var_dump($response->getBody()); die;
    }

This var_dump gives me:

{
  ["stream":protected]=>
  resource(318) of type (stream)
  ["meta":protected]=>
  array(6) {
    ["wrapper_type"]=>
    string(3) "PHP"
    ["stream_type"]=>
    string(4) "TEMP"
    ["mode"]=>
    string(3) "w+b"
    ["unread_bytes"]=>
    int(0)
    ["seekable"]=>
    bool(true)
    ["uri"]=>
    string(10) "php://temp"
  }
  ["readable":protected]=>
  NULL
  ["writable":protected]=>
  bool(true)
  ["seekable":protected]=>
  NULL
  ["size":protected]=>
  NULL
  ["isPipe":protected]=>
  NULL
  ["finished":protected]=>
  bool(false)
  ["cache":protected]=>
  NULL
}

and $response->getBody()->getContents() gives me empty string.

In Postman I normally see JSON response with some data.

In app/middleware.php I’ve added $app->addBodyParsingMiddleware(); - without it it was impossible for my controller to read any payload I was sending to the POST route.

What am I doing wrong?

Whoa! I’ve found this: $response->getBody()->getContents() returns always empty content · Issue #48 · 8p/EightPointsGuzzleBundle · GitHub

I’ve managed to get the body by casting it to a string.

(string) $response->getBody()

Now I can json_decode and assert but it’s bizarre. Is this a proper way to do this? I’m new to Slim 4.

Yes, this is also the correct way in Slim to get the body content as a string.

When you cast the body, PHP calls the magic method __toString().
You could also call the __toString() method directly instead, but that doesn’t look very nice.

$content = $request->getBody()->__toString();

To recommend way is this:

$content = (string)$response->getBody();