Chapters
39 Chapters
|
4:45:13
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3, <8.0
Subscribe to download the code!Compatible PHP versions: ^7.1.3, <8.0
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
23.
Testing, Updating Roles & Refreshing Data
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
This tutorial works great for Symfony 5 and API Platform 2.5/2.6.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3, <8.0",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^2.1", // v2.4.5
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // 1.13.2
"doctrine/doctrine-bundle": "^1.6", // 1.11.2
"doctrine/doctrine-migrations-bundle": "^2.0", // v2.0.0
"doctrine/orm": "^2.4.5", // v2.7.2
"nelmio/cors-bundle": "^1.5", // 1.5.6
"nesbot/carbon": "^2.17", // 2.21.3
"phpdocumentor/reflection-docblock": "^3.0 || ^4.0", // 4.3.1
"symfony/asset": "4.3.*", // v4.3.2
"symfony/console": "4.3.*", // v4.3.2
"symfony/dotenv": "4.3.*", // v4.3.2
"symfony/expression-language": "4.3.*", // v4.3.2
"symfony/flex": "^1.1", // v1.21.6
"symfony/framework-bundle": "4.3.*", // v4.3.2
"symfony/http-client": "4.3.*", // v4.3.3
"symfony/monolog-bundle": "^3.4", // v3.4.0
"symfony/security-bundle": "4.3.*", // v4.3.2
"symfony/twig-bundle": "4.3.*", // v4.3.2
"symfony/validator": "4.3.*", // v4.3.2
"symfony/webpack-encore-bundle": "^1.6", // v1.6.2
"symfony/yaml": "4.3.*" // v4.3.2
},
"require-dev": {
"hautelook/alice-bundle": "^2.5", // 2.7.3
"symfony/browser-kit": "4.3.*", // v4.3.3
"symfony/css-selector": "4.3.*", // v4.3.3
"symfony/maker-bundle": "^1.11", // v1.12.0
"symfony/phpunit-bridge": "^4.3", // v4.3.3
"symfony/stopwatch": "4.3.*", // v4.3.2
"symfony/web-profiler-bundle": "4.3.*" // v4.3.2
}
}
3 Comments
Hi there!
I wrote this test:
At the beginning,
$user = $em->getRepository(UserObject::class)->find($user->getId());was uncommented. But then I just wanted to check what would be the error wihout "reloading the user from the database"... and surprise it works fine...I am confused because I understand why we need to refresh the user from the database after a request, but in this test it seems that it is not needed... Am I missing something?
Hey Simon L.!
To be honest, this stuff is really tricky :/. I believe I can answer your question, but you'll see how tricky it is when I do it ;). Here is the flow:
1) When you call
$client = self::createClient();, behind the scenes, this boots a Symfony kernel/container.2) When you call
$em = $this->getEntityManager();, that causes the entity manager to be instantiated from that container. That same entity manager object is used, obviously, to create the user and token.3) When you call
$client->request(), because you have NOT made a request yet through this client, it makes a "fake" request into Symfony but re-uses the same kernel/container that we've been working with.This means that when your API Platform code runs, it uses the same EntityManager as your test. And so, when your API code, for example, queries for the User object, the EntityManager is smart enough to return the same User object (in memory) as the one you have in your test. So when your API code updates that User object, it is updating the same User object in memory as your test.So... THAT is why you don't need to refresh: the User object in your test === the User object that's used inside the request.
Of course, the next question is: then why do we ever need to refresh objects? If you proceed to make a second
$client->request(), THIS time, the client object says "oh, I have already made a request. So I should shutdown my kernel and create a new Container" - you can see that in this method: https://github.com/symfony/symfony/blob/5.x/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php#L144-L157This means that the second request will use a different container than your test. And this means that, inside your API code in that request, a NEW EntityManager object will be created. When your API code queries for the User object this time, that EntityManager will not have already queried for that User object (like in the first request), and so it will make a fresh query and (most importantly) will create & use a fresh User object. Then, that NEW User object will be modified by the rest of your API code. In this case, the User object in your test !== the User object being used by your API request.
So... make sense? 🙃 This is just a tricky area: you need a container in your test so you can access services. And Symfony needs a container for each request... but to be realistic (since in real life, 2 requests are totally isolated), it deletes and re-creates a new container for each request. The accidental end result is that the container in your test === the container in your request for the FIRST request only 😛
Cheers!
Thank you weaverryan :)
"Houston: no signs of life"
Start the conversation!