title: How can I mock an autowired service to symfony controller in phpunit functional tests?
body: <h1>Non-problematic context</h1>
  
  <p>Let's say in Symfony 3.3 we have a default controller that paints "Hello, world!":</p>
  
  <pre><code>class DefaultController extends Controller
  {
      public function indexAction() : Response
      {
          return new Response( 'Hello, world!' );
      }
  }
  </code></pre>
  
  <p>If I want to test it, I just create a WebTestCase and do some assertions on the client or the crawler, for example </p>
  
  <pre><code>class DefaultControllerTest extends WebTestCase
  {
      public function testIndex()
      {
          $client = static::createClient();
  
          $crawler = $client-&gt;request( 'GET', '/route/to/hello-world/' );
  
          $this-&gt;assertEquals( 200, $client-&gt;getResponse()-&gt;getStatusCode() );
          $this-&gt;assertContains( 'Hello', $crawler-&gt;filter( 'body' )-&gt;text() );
      }
  }
  </code></pre>
  
  <p>This just works fine.</p>
  
  <h1>Problematic context</h1>
  
  <p>Let's say we have some unit-tested services. For example a <code>IdGenerator</code> service that creates new Ids based on a certain algorithm when we need one, and they are just plain text:</p>
  
  <pre><code>class IdGenerator
  {
      public function generateNewId() : string;
  }
  </code></pre>
  
  <p>Say we I inject it via <strong>autowiring</strong> into the controller. And we expect that the controller says something like <code>Hello, world, on request 8bfcedbe1bf3aa44e0545375f0e52f6b969c50fb!</code> where this bunch of characters come from the IdGenerator.</p>
  
  <pre><code>class DefaultController extends Controller
  {
      public function indexAction( IdGenerator $idGenerator ) : Response
      {
          $id = $idGenerator-&gt;generateNewId();
          $message = sprintf( 'Hello, world, on request %s!', $id );
          return new Response( $message );
      }
  }
  </code></pre>
  
  <p>Of course I could reload the page multiple times in a browser and see the text changing over time with new Ids each time.</p>
  
  <p>But this is not the way automated tests should world. We should mock the IdGenerator, so it returns a specific <code>id</code> to assert:</p>
  
  <pre><code>class DefaultControllerTest extends WebTestCase
  {
      public function testIndex()
      {
          $id = 'test-id-test-id-test-id';
          $idGenerator = $this-&gt;createMock( IdGenerator::class );
          $idGenerator-&gt;method( 'generateNewId' )-&gt;willReturn( $id );
  
          // What do I have to do with $idGenerator now here????
  
          $client = static::createClient();
  
          // Do something else here?
  
          $crawler = $client-&gt;request( 'GET', '/admin/flights/search/' );
  
          $this-&gt;assertEquals( 200, $client-&gt;getResponse()-&gt;getStatusCode() );
          $this-&gt;assertContains( $id, $crawler-&gt;filter( 'body' )-&gt;text() );
      }
  }
  </code></pre>
  
  <p>I have already tested to get the container, from the kernel, from the client, and set the service there and it does <strong>not</strong> work:</p>
  
  <pre><code>    $id = 'test-id-test-id-test-id';
      $idGenerator = $this-&gt;createMock( IdGenerator::class );
      $idGenerator-&gt;method( 'generateNewId' )-&gt;willReturn( $id );
  
      $client = static::createClient();
      $kernel = $client-&gt;getKernel();
      $container = $kernel-&gt;getContainer();
      $container-&gt;set( 'My\Nice\Project\Namespace\IdGenerator', $idGenerator );
  </code></pre>
  
  <p>It still gets the autowired one instead of the one I want (the mock).</p>
  
  <h1>Question</h1>
  
  <p>How can I setup the WebTestCase so the autowiring wires my mocked service?</p>