How can I mock an autowired service to symfony controller in phpunit functional tests?

Non-problematic context

Let’s say in Symfony 3.3 we have a default controller that paints “Hello, world!”:

class DefaultController extends Controller
{
    public function indexAction() : Response
    {
        return new Response( 'Hello, world!' );
    }
}

If I want to test it, I just create a WebTestCase and do some assertions on the client or the crawler, for example

class DefaultControllerTest extends WebTestCase
{
    public function testIndex()
    {
        $client = static::createClient();

        $crawler = $client->request( 'GET', '/route/to/hello-world/' );

        $this->assertEquals( 200, $client->getResponse()->getStatusCode() );
        $this->assertContains( 'Hello', $crawler->filter( 'body' )->text() );
    }
}

This just works fine.

Problematic context

Let’s say we have some unit-tested services. For example a IdGenerator service that creates new Ids based on a certain algorithm when we need one, and they are just plain text:

class IdGenerator
{
    public function generateNewId() : string;
}

Say we I inject it via autowiring into the controller. And we expect that the controller says something like Hello, world, on request 8bfcedbe1bf3aa44e0545375f0e52f6b969c50fb! where this bunch of characters come from the IdGenerator.

class DefaultController extends Controller
{
    public function indexAction( IdGenerator $idGenerator ) : Response
    {
        $id = $idGenerator->generateNewId();
        $message = sprintf( 'Hello, world, on request %s!', $id );
        return new Response( $message );
    }
}

Of course I could reload the page multiple times in a browser and see the text changing over time with new Ids each time.

But this is not the way automated tests should world. We should mock the IdGenerator, so it returns a specific id to assert:

class DefaultControllerTest extends WebTestCase
{
    public function testIndex()
    {
        $id = 'test-id-test-id-test-id';
        $idGenerator = $this->createMock( IdGenerator::class );
        $idGenerator->method( 'generateNewId' )->willReturn( $id );

        // What do I have to do with $idGenerator now here????

        $client = static::createClient();

        // Do something else here?

        $crawler = $client->request( 'GET', '/admin/flights/search/' );

        $this->assertEquals( 200, $client->getResponse()->getStatusCode() );
        $this->assertContains( $id, $crawler->filter( 'body' )->text() );
    }
}

I have already tested to get the container, from the kernel, from the client, and set the service there and it does not work:

    $id = 'test-id-test-id-test-id';
    $idGenerator = $this->createMock( IdGenerator::class );
    $idGenerator->method( 'generateNewId' )->willReturn( $id );

    $client = static::createClient();
    $kernel = $client->getKernel();
    $container = $kernel->getContainer();
    $container->set( 'My\Nice\Project\Namespace\IdGenerator', $idGenerator );

It still gets the autowired one instead of the one I want (the mock).

Question

How can I setup the WebTestCase so the autowiring wires my mocked service?

How can I mock an autowired service to symfony controller in phpunit functional tests?