PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Monday, January 10, 2022

[FIXED] Symfony 5: how do I mock HttpClientInterface in integration test?

 January 10, 2022     dependency-injection, functional-testing, php, symfony     No comments   

Issue

I have a controller end-point that does an external API request under hood which I can't really make each time I run tests.

I'm using HttpClientInterface to make the request and now my idea is to replace it with MockHttpClient. So here is what I have so far:

class MyControllerTest extends WebTestCase
{
    public function testSomething(): void
    {
        $client = static::createClient();

        $response = new MockResponse(null, ['http_code' => 200]);
        $client->getContainer()->set(HttpClientInterface::class, new MockHttpClient($response));

        $client->request('GET', '/my-end-point');

        self::assertResponseIsSuccessful();
    }
}

But it gives me the following error:

The "Symfony\Contracts\HttpClient\HttpClientInterface" service is private, you cannot replace it

which is kinda makes sense. Is there a better solution or how to overcome the problem?


Solution

In a Symfony environment services are private, but this is not a problem because you are getting them in your controllers, services, etc through Dependency Injection, meaning that it is Symfony itself that takes care of it.

When trying to test, you may end up, like in your case, setting the mocked class in your container directly.

This will throw the error you see.

To overcome this error, in your services.yaml file located in the config folder, just add the following lines at the bottom:

when@test:
    services:
        _defaults:
            public: true

        test.Symfony\Contracts\HttpClient\HttpClientInterface: '@Symfony\Contracts\HttpClient\HttpClientInterface'

what you are doing here, is telling Symfony that during tests you will have a public Service called test.Symfony\Contracts\HttpClient\HttpClientInterface that it is a copy of the HTTPClientInterface class.

Now, in your test code you can do the following:

$response = new MockResponse(null, ['http_code' => 200]);
$client->getContainer()->('test.Symfony\Contracts\HttpClient\HttpClientInterface', new TraceableHttpClient(new MockHttpClient($response)));


Answered By - ThomasSquall
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing