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

RefreshDatabaseTrait is not executed in time #30

Closed
renja-g opened this issue Jan 4, 2023 · 11 comments
Closed

RefreshDatabaseTrait is not executed in time #30

renja-g opened this issue Jan 4, 2023 · 11 comments

Comments

@renja-g
Copy link

renja-g commented Jan 4, 2023

I was trying to use RefreshDatabaseTrait for API testing but for some reason the assert gave me 404.

<?php

namespace App\Tests\Functional;

use App\test\CustomApiTestCase;
use Hautelook\AliceBundle\PhpUnit\RefreshDatabaseTrait;


class UserResourceTest extends CustomApiTestCase
{
    use RefreshDatabaseTrait;

    public function testGetItemUser(): void
    {
        $client = static::createClient();
        
        $user = $this->createUser($client, 'test_user_1@example.com', 'Test_password_1!', 'Test User 1');

        $client->request('GET', '/api/users/' . $user->getId());
        $this->assertResponseStatusCodeSame(401, 'GET item (no auth)');
    }
}

After a long time of testing, I found out that with this code only the first assert fails.

    public function testGetItemUser(): void
    {
        $client = static::createClient();

        $user = $this->createUser($client, 'test_user_1@example.com', 'Test_password_1!', 'Test User 1');
        
        $client->request('GET', '/api/users/' . $user->getId());
        $this->assertResponseStatusCodeSame(401, 'GET item (no auth 1)');

        $client->request('GET', '/api/users/' . $user->getId());
        $this->assertResponseStatusCodeSame(401, 'GET item (no auth 2)');
    }

It feels like the database refresh is not finishing in time so that the first user is deleted

1. database refresh start
2. Create User
3. database refresh end
@renja-g
Copy link
Author

renja-g commented Jan 4, 2023

nvm, I'm not even creating two users.
but it is ward because if I remove use RefreshDatabaseTrait;
the code works like this:

    public function testGetItemUser(): void
    {
        $client = static::createClient();
        
        $user = $this->createUser($client, 'test_user_1@example.com', 'Test_password_1!', 'Test User 1');

        $client->request('GET', '/api/users/' . $user->getId());
        $this->assertResponseStatusCodeSame(401, 'GET item (no auth)');
    }

@theofidry
Copy link
Owner

Isn't it an issue with static::createClient() that re-creates a kernel with maybe a different connection?

@renja-g
Copy link
Author

renja-g commented Jan 4, 2023

Isn't it an issue with static::createClient() that re-creates a kernel with maybe a different connection?

But then why does it work if I remove the use RefreshDatabaseTrait;

@renja-g
Copy link
Author

renja-g commented Jan 5, 2023

also, when running the full test the first two tests run true fine but when hitting the third I get an SQL Duplicate entry error for "test_user_1@example.com" but this should not be happening if the reset would have already happend.

<?php

namespace App\Tests\Functional;

use App\test\CustomApiTestCase;
use Hautelook\AliceBundle\PhpUnit\RefreshDatabaseTrait;


class UserResourceTest extends CustomApiTestCase
{
    use RefreshDatabaseTrait;

    // Tests:
    // POST (no auth)
    public function testPostUser(): void
    {
        $client = static::createClient();

        // POST (no auth)
        $this->createUser($client, 'test_user_1@example.com', 'Test_password_1!', 'Test User 1');
        $this->assertResponseStatusCodeSame(201, 'POST (no auth)');
    }

    // Tests:
    // GET collection (no auth)
    // GET collection (auth)
    // GET collection (admin auth)
    public function testGetCollectionUser(): void
    {
        $client = static::createClient();

        // GET collection (no auth)
        $client->request('GET', '/api/users');
        $this->assertResponseStatusCodeSame(401, 'GET collection (no auth)');


        // GET collection (auth)
        $user = $this->createUser($client, 'test_user_1@example.com', 'Test_password_1!', 'Test User 1');
        $token = $this->createAuth($client, $user);
        $client->request('GET', '/api/users', [
            'headers' => [
                'Authorization' => 'Bearer ' . $token,
            ],
        ]);
        $this->assertResponseStatusCodeSame(403, 'GET collection (auth)');


        // GET collection (admin auth)
        $admin = $this->createAdmin($client, 'test_admin_1@example.com', 'Test_password_1!', 'Test Admin 1');
        $token = $this->createAuth($client, $admin);
        $client->request('GET', '/api/users', [
            'headers' => [
                'Authorization' => 'Bearer ' . $token,
            ],
        ]);
        $this->assertResponseStatusCodeSame(200, 'GET collection (admin auth)');
    }


    // Tests:
    // GET item (no auth)
    // GET item (auth owne)
    // GET item (auth *)
    // GET item (admin auth own)
    // GET item (admin auth *)
    public function testGetItemUser(): void
    {
        $client = static::createClient();
        // GET item (no auth)
        $user = $this->createUser($client, 'test_user_1@example.com', 'Test_password_1!', 'Test User 1');

        $client->request('GET', '/api/users/' . $user->getId());
        $this->assertResponseStatusCodeSame(401, 'GET item (no auth 2)');

        $client->request('GET', '/api/users/' . $user->getId());
        $this->assertResponseStatusCodeSame(401, 'GET item (no auth 2)');
    }
}

@d0niek
Copy link

d0niek commented Feb 16, 2024

I'm not sure but it looks similar to my problem.

When I load fixtures from files (use R...DatabaseTrait in test class) I can't save any new entity to the database by using EntityManager or by making a request to the api.

@renja-g confirm if it's the same in your case. If not @theofidry I'll create a new issue.

@d0niek
Copy link

d0niek commented Feb 19, 2024

I've fixed my issue. The problem was that the "base test class" and specific "test class" use R...DatabaseTrait so it was loaded twice. With this for loaded entities as fixtures every new EntityClass was marked as MANAGED by doctrine EntityManager (UnitOfWork).

@theofidry
Copy link
Owner

so it was loaded twice

I wonder if there would be a way to detect this and throw an error in this case?

@d0niek
Copy link

d0niek commented Feb 20, 2024

I don't know exactly the tests flow but is bootKernel run before test-case and ensureKernelShutdown after? If yes maybe add some flag (?) there and check it?

@theofidry
Copy link
Owner

Actually it looks like this is already handled? https://github.com/theofidry/AliceBundle/blob/master/src/PhpUnit/RefreshDatabaseTrait.php#L38 So there maybe more to it

@d0niek
Copy link

d0niek commented Feb 20, 2024

Yes, I saw it! But ReloadDatabaseTrait is missing it.

@theofidry
Copy link
Owner

I think this may be related to mixing up Refresh and Reload.

The fix is NOT to add what is in Refresh to Reload. The idea of Reload is to populate the database at kernel boot, if there is already fixtures a purge (via delete or truncate) is done before populating the database. So even calling it several times over should be fine (although expensive for no reasons).

Where this will get messy is if Reload is mixed up with Refresh. Indeed Refresh populates the DB once and then uses transactions to rollback. But purging with a truncate will be effective and remove the data regardless of the transaction. Calling it twice should also have no effect (besides having nested transactions).

I am not sure if this really addresses the original case, but I will close this as I cannot find anything. if you encounter the problem and want me to look into it please provide a small reproducer that I can debug.

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

Successfully merging a pull request may close this issue.

3 participants