From b665b5e193b9240902030b5e8e6300f15b1bcc0e Mon Sep 17 00:00:00 2001 From: Mathieu Lechat Date: Sat, 26 Aug 2023 11:40:56 +0200 Subject: [PATCH] [Testing] Create a section dedicated to sending multiple requests in one functional test --- testing.rst | 59 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/testing.rst b/testing.rst index 7cb5f906046..0d30887be86 100644 --- a/testing.rst +++ b/testing.rst @@ -619,15 +619,58 @@ This allows you to create all types of requests you can think of: :ref:`framework.test ` option is enabled). This means you can override the service entirely if you need to. -.. caution:: +Multiple requests in one test +............................. + +After you send one request, subsequent ones will make the client reboot +the kernel, recreating the container from scratch. +This ensures that requests are "isolated" using "new" service objects, +but can cause some unexpected behaviors. For example, the security token will +be cleared, Doctrine entities will be "detached"… + +Calling the client's +:method:`Symfony\\Bundle\\FrameworkBundle\\KernelBrowser::disableReboot` +method is the first step to work around this, as this will reset the kernel +instead of rebooting it. Now, resetting the kernel will call the reset method +of every ``kernel.reset`` tagged service, which will **also** clear the +security token, detach entities and so on. + +As such, the next step is to create a +:doc:`compiler pass ` to remove the +``kernel.reset`` tag from these services in your test environment:: + + // src/Kernel.php + namespace App; + + use App\DependencyInjection\Compiler\CustomPass; + use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; + use Symfony\Component\DependencyInjection\ContainerBuilder; + use Symfony\Component\HttpKernel\Kernel as BaseKernel; + + class Kernel extends BaseKernel + { + use MicroKernelTrait; + + // … - Before each request, the client reboots the kernel, recreating - the container from scratch. - This ensures that every requests are "isolated" using "new" service objects. - Also, it means that entities loaded by Doctrine repositories will - be "detached", so they will need to be refreshed by the manager or - queried again from a repository. - You can disable this behavior by calling the :method:`disableReboot() ` method. + protected function build(ContainerBuilder $container): void + { + if ('test' === $this->environment) { + $container->addCompilerPass(new class() implements CompilerPassInterface { + public function process(ContainerBuilder $container): void + { + // prevents the security token to be cleared + $container->getDefinition('security.token_storage')->clearTag('kernel.reset'); + + // prevents entities to be detached + $container->getDefinition('doctrine')->clearTag('kernel.reset'); + + // … + } + }); + } + } + } Browsing the Site .................