Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FrameworkBundle] Allow setting private services with the test container #48938

Merged
merged 1 commit into from Jan 13, 2023

Conversation

nicolas-grekas
Copy link
Member

Q A
Branch? 6.3
Bug fix? no
New feature? yes
Deprecations? no
Tickets -
License MIT
Doc PR -

This PR allows mocking a service for a test case. A typical example could be for HttpClient:

static::getContainer()->set('example.client', new MockHttpClient(...));

// do stuff that will use `example.client` and will get mock responses instead of using the network

@damienalexandre
Copy link
Contributor

Really looking forward this one! Thanks a lot!

@bastnic
Copy link
Contributor

bastnic commented Jan 10, 2023

Awesome!

@Seldaek
Copy link
Member

Seldaek commented Jan 10, 2023

Is this cool? Yes I think so. It'd make tests less brittle if you don't have to instantiate smth but can rely on auto wiring too.

Just one thought: could it detect if a service which was set is then not used during a test and output a warning? That'd allow to catch errors where you configure stuff that's useless / dead code. Possibly would back fire tho and be more annoying than useful :)

@nicolas-grekas
Copy link
Member Author

@Seldaek that'd be neat but I don't know how we could make that work. There is no infrastructure in the container to know when a service is injected into another one, and even less to know when such a service is actually used.

On a case by case basis, it's doable of course:

$client = new TraceableHttpClient(new MockHttpClient(...));
static::getContainer()->set('example.client', $client);

// do stuff

// do expectations using TraceableHttpClient's API

@tgalopin
Copy link
Member

This would also be super useful to mock the clock (I do it all the time, mocking in the config isn't enough to test all cases):

static::getContainer()->set(ClockInterface::class, new MockClock('2022-11-23 00:00:00', 'UTC'));

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Jan 10, 2023

@tgalopin see also #48642
TL;DR, use ClockSensitiveTrait::mockTime().

@nicolas-grekas nicolas-grekas force-pushed the test-set-service branch 2 times, most recently from fd0d04c to 99883aa Compare January 10, 2023 17:42
Copy link
Member

@dunglas dunglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

@fabpot
Copy link
Member

fabpot commented Jan 13, 2023

Thank you @nicolas-grekas.

@Bilge
Copy link
Contributor

Bilge commented Jan 18, 2023

  1. How does this work given the container has already been compiled and, where such services are replaced, the object they are replacing has already been injected into dependents and thus will not see the effect of this replacement?
  2. For @nicolas-grekas specifically, seeing as this PR is at odds with your original assessment, what changed?

@stof
Copy link
Member

stof commented Jan 18, 2023

@Bilge you must do the injection before services are instantiated.
Compiling a container is not when instantiation happens.

@stof
Copy link
Member

stof commented Jan 18, 2023

And the special TestContainer allowing you to retrieve private services already has a restriction that this does not support inlined services. This injection has the same restriction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet