api-platform icon indicating copy to clipboard operation
api-platform copied to clipboard

[Test] Client reboots between requests

Open sylfabre opened this issue 5 years ago • 7 comments

Description
I'm using the AliceBundle for my fixtures, and this bundle relies on MySQL transactions to get a clean set of data between tests:

  • When the test kernel is booted, a MySQL transaction starts
  • When the test kernel shutdowns, the current MySQL transaction is rolled back

Thanks to the ApiTestCase, it is very easy to create a client to run API Platform requests in the context of functional tests. During its creation, a Symfony kernel is booted and is "injected" in the test client. => It means that the test and "server" answering the requests share the same kernel so share the same container so share the same Doctrine connections.

But by default, once the Symfony Client has served a request, it will reboot before serving the next one.

In my case, a second request will use another container so another Doctrine connection which is unaware of the current MySQL transaction (as it is isolated by-design) of the test scope.

This behavior of Symfony is not documented and unexpected which makes poor developer experience when using the ApiTestCase.

An easy fix is to call the \Symfony\Bundle\FrameworkBundle\Client::disableReboot() method.

I may also be missing a point in the current implementation.

Would you accept a PR to call disableReboot() in the createClient() method?

Example

<?php

// Method part of a test suite using the AliceBundle
function test1()
{
    $client = self::createClient; // This begins a MySQL transaction

    $user = new User();
    $em = self::$container->get(EntityManagerInterface::class);
    $em->persist($user);
    $em->flush();

    $client->request('GET', '/user/' . $user->getId()); // HTTP 200 => OK
    $client->request('GET', '/user/' . $user->getId()); // HTTP 404 => Unexpected
}

// Method part of a test suite using the AliceBundle
function test2()
{
    $client = self::createClient; // This begins a MySQL transaction
    $client->disableReboot();

    $user = new User();
    $em = self::$container->get(EntityManagerInterface::class);
    $em->persist($user);
    $em->flush();

    $client->request('GET', '/user/' . $user->getId()); // HTTP 200 => OK
    $client->request('GET', '/user/' . $user->getId()); // HTTP 200 => OK
}

sylfabre avatar Oct 17 '20 20:10 sylfabre

We should at least document that solution. When you disable the reboot, the isolation by-test is still working?

soyuka avatar Oct 19 '20 10:10 soyuka

When you disable the reboot, the isolation by-test is still working?

@soyuka Yes it is because the Alice bundle rolls back the MySQL transaction when a call to ensureKernelShutdown() is made.

And this method is called during the tearDown() call.

sylfabre avatar Oct 19 '20 13:10 sylfabre

WDYT about fixing this directly in symfony's client though?

soyuka avatar Oct 21 '20 07:10 soyuka

@soyuka Because I am not aware of all usages of the Symfony's KernelBrowser: it may have use cases where rebooting after each request is legitimate. Changing it would break these use cases.

I'll still open an issue at Symfony so experts can discuss it.

edit: Symfony\Bundle\FrameworkBundle\Client is deprecated in SF 4.3. I'll try to upgrade to SF5 to check if the issue persists

sylfabre avatar Oct 21 '20 09:10 sylfabre

I've given some more thoughts about this, I don't think that disableReboot should be the default but it should defiitely be documented.

soyuka avatar Nov 05 '20 16:11 soyuka

I can confirm this issue still exists in Symfony 5. Since it looks like this is a complicated topic and there is no consensus yet where the fix should be implemented between API platform, Symfony and the alice bundle, I have created a documentation PR to at least document the current situation until this issue is properly resolved.

carlobeltrame avatar May 19 '21 14:05 carlobeltrame

What i also recognized: If you use disableReboot and want to collect e.g. mails from profiler from second request, it is not added.

develth avatar May 07 '25 17:05 develth