How to pass JSON in POST method with PhpUnit Testing?

I prefer using GuzzleHttp for external requests :

use GuzzleHttp\Client;

$client = new Client();

$response = $client->post($url, [
    GuzzleHttp\RequestOptions::JSON => ['title' => 'title', 'body' => 'body']
]);

Note: GuzzleHttp should be installed with e.g. using composer.

But you can always use client bundled with Symfony:

public function testJsonPostPageAction()
{
    $this->client = static::createClient();
    $this->client->request(
        'POST', 
        '/api/v1/pages.json',  
        array(),
        array(),
        array('CONTENT_TYPE' => 'application/json'),
        '[{"title":"title1","body":"body1"},{"title":"title2","body":"body2"}]'
    );
    $this->assertJsonResponse($this->client->getResponse(), 201, false);
}

protected function assertJsonResponse($response, $statusCode = 200)
{
    $this->assertEquals(
        $statusCode, $response->getStatusCode(),
        $response->getContent()
    );
    $this->assertTrue(
        $response->headers->contains('Content-Type', 'application/json'),
        $response->headers
    );
}

Maybe it's a bit late... but it can help someone.

with this you can build a generic POST request and will be accepted by your controller. it's on Symfony 4.x using framework's HTTP client

use Symfony\Component\HttpFoundation\Request;

$request = new Request([], [], [], [], [], ['HTTP_CONTENT_TYPE' => 'application/json'], {"foo":"bar"}));

A little late, but for Symfony 5, you have the jsonRequest accessible via any WebTestCase

<?php
$this->client = static::createClient();

$this->client->jsonRequest('POST', '/myJsonEndpoint', [
    'key' => 'value'
]);