symfony-docs icon indicating copy to clipboard operation
symfony-docs copied to clipboard

Symfony docs should explain how to 1. use and overwrite services in 6.x and 2. that all need to be public in test

Open torian257x opened this issue 3 years ago • 2 comments

https://symfony.com/doc/current/testing.html

lacks information of say

class UnderstandSymfonyTest extends KernelTestCase
{
...

self::getContainer()->set(IDevJobService::class, $mockDevJobService);
...

and that all services need to be set to public in test to use them e.g.

when@test:
    services:
        App\Service\Concerns\IDevJobService:
          class: App\Tests\Classes\TestDevJobService
          autowire: true
          public: true

torian257x avatar Aug 12 '22 13:08 torian257x

Does the Retrieving Services in the Test section answer your question? The note at the end of this section explains how to access to private services.

I don't understand the examples, it looks like a mock service is injected in the second code block, and it is replaced by another mock in the first code block.

alexislefebvre avatar Aug 12 '22 13:08 alexislefebvre

first code block shows how you can inject a mock service at runtime - or any other class. The reason to use it that way is to set the service at runtime to what you want it to be during testing. For all code references

second shows how you set a service to public (this gets overwritten by first code block)

if you want to leave out how to set a test service to public, then leave out the second block. maybe move the note to the top, right below the heading.

the first one is important though imho

torian257x avatar Aug 12 '22 14:08 torian257x

Someone in the symfony slack asked why they were receiving a concrete CurlClient instead of a MockHttpClient in their test. They were specifically confused by this wording:

MockHttpClient implements the HttpClientInterface, just like any actual HTTP client in this component. When you type-hint with HttpClientInterface your code will accept the real client outside tests, while replacing it with MockHttpClient in the test.

And thought it implied the service container would use the mock in the test environment automatically.

The solution was to use the container->set(...) method in their test to swap out the real client for the mock, but there is a lack of documentation referencing it. The only example I could find (very similar to the one provided by torian) was provided by Nicolas Grekas in this pr.

I think having it as part of the Mocking Dependencies section of the Testing docs would be great as I agree that it's very important. (I found out about it from my IDE, but wasn't sure if it was an appropriate method to use in testing). And then also adding another example to, or changing the current example, in the FullExample section of the HttpClient docs (using set would be less verbose than manually instantiating services).

Aweptimum avatar May 15 '23 16:05 Aweptimum

and that all services need to be set to public in test to use them e.g.

when@test:
    services:
        App\Service\Concerns\IDevJobService:
          class: App\Tests\Classes\TestDevJobService
          autowire: true
          public: true

I don't understand why the autowire: true is required here.

Here is the default config for services:

services:
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

To my knowledge, it should be inherited by the services in the [email protected] block, isn't it?

It looks like users have to declare the autowiring globally for the test services, like this:

when@test:
    services:
        _defaults:
            autowire: true
            autoconfigure: true

        App\DataFixtures\ORM\:
            resource: '../src/DataFixtures/ORM/*'
            tags: [ 'doctrine.fixture.orm' ]

Or for every service:

when@test:
    services:
        App\DataFixtures\ORM\:
            resource: '../src/DataFixtures/ORM/*'
            autowire: true
            tags: [ 'doctrine.fixture.orm' ]

(this is not a support question, I just want to ensure that we will use the right syntax when we'll update the docs)

alexislefebvre avatar May 16 '23 19:05 alexislefebvre

I think the updated testing contents already cover what this issue asked for:

  • Mocking dependencies, setting services in container: https://symfony.com/doc/current/testing.html#mocking-dependencies
  • Getting public/private services from the container in tests: https://symfony.com/doc/current/testing.html#retrieving-services-in-the-test

So, I'm closing this as fixed. If there's something missing, please add a comment and we'll take care of it. Thanks!

javiereguiluz avatar Sep 08 '23 06:09 javiereguiluz