Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Symfony tests how to pass depencencies to services via container

I’m writing tests for a Symfony 4.4 app and I need to mock a service named TokenService which is a dependency of some classes that I need to test (repositories, services), but I’m not sure how to proceed to pass some dependencies via DI :

 self::$container->get('App\Services\classToTest') // Not able to pass dependencies ?

Am I forced to instantiate the class and do something like this :

$classToTest = new \App\Services\classToTest($depencencyOne,$tokenMock,...)

Also, I need to mock only one of the dependencies, so do I have to pass all the other dependencies anyway ?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can get() from the testing service container but you can also set() !

I can give a real example I recently had where I needed to replace the HttpClient with its mock implementation in some tests:

// Here I replace the service with a mock implementation (a PHPUnit mock can work too)
self::getContainer()->set(HttpClientInterface::class, new MockHttpClient([
    new MockResponse('{"some":"JSON"}'),
    new MockResponse('{"other":"JSON"}'),
]));

// Here $myService will get the mock injected instead of the original HTTP Client
$myService = self::getContainer()->get(MyService::class);

But it should be noted that I had to make the service public to be allowed to overwrite it:

# services.yaml
when@test:
    services:
        Symfony\Contracts\HttpClient\HttpClientInterface:
            alias: '.debug.http_client'
            public: true

If you don’t (or can’t) replace a dependency in the service container, then yes you will need to instantiate the tested service yourself and get every dependency:

$myService = new MyService(
     self::getContainer()->get(RealService::class),
     $someMockDependency
);

If the issue comes from your own code, be sure to follow good practices to make your code easier to test (mostly dependency injection and dependency inversion principles).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading