Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

FMK's avatar
Level 4

Laravel Pest test ignore not resetting mariadb autoincrement ids

I have a laravel pest test that checks a redirect after data is submitted to a controller to create a client.

it('redirects to the clients show page', function () {
    $user = User::factory()->asAdmin()->create();

    auth()->login($user);

    post(route('clients.store'), [
        'name' => 'Test Client',
        'description' => 'Test Description',
        'poc' => 'Test POC',
        'poc_email' => 'Test POC Email',
        'image_path' => 'Test Image Path',
    ])->assertRedirect(route('clients.show', Client::first()));
});

In isolation mode (only this test is executed) it works without a problem, but once i run the whole test suite with multiple test before this one (creating and removing clients), the test fails because the auto increment is not reset after each test resulting in this error message:

Failed asserting that two strings are equal.
Expected :'http://localhost/clients/4'
Actual   :'http://localhost/clients/1'
<Click to see difference>

at vendor/laravel/framework/src/Illuminate/Testing/TestResponse.php:311
at vendor/laravel/framework/src/Illuminate/Testing/TestResponse.php:178
at tests/Feature/Controllers/ClientController/StoreTest.php:87
at vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:177

I'm using the refresh database trait for my pest test and I know that this behaviour is expected since for performance reasons the auto increment indicies are not reset after each test. With the DatabaseMigrations trait it also works but it goes up from ~1sec to nearly 20sec so this is not realy a valid option!

Here are some more information about my setup: DB: MariaDB 11.2 PHP: 8.3.1 Laravel: 10.40

The interesting part is that the route with the freshly created client model redirects to the correct id of 1 but the Client::first() returns a client with a id of 4.

Also this testsuite works with sqlite without any problems!

So my question is, how do I get a test that tests that same but does not rely on the inconsistent id of the client in this case?

Thanks for your help!

0 likes
3 replies
tisuchi's avatar

@fmk Maybe try this:


it('redirects to the clients show page', function () {
    $user = User::factory()->asAdmin()->create();

    auth()->login($user);

    $response = post(route('clients.store'), [
        'name' => 'Test Client',
        'description' => 'Test Description',
        'poc' => 'Test POC',
        'poc_email' => 'Test POC Email',
        'image_path' => 'Test Image Path',
    ]);

    $createdClient = Client::latest()->first();

    $response->assertRedirect(route('clients.show', $createdClient));
});

The latest() method will order the records by the created_at timestamp, and will ensure that the most recent record is fetched.

I think it will not affected by the auto-increment in the database.

FMK's avatar
Level 4

@tisuchi Thanks for your suggestion but the same error is still present. The change of order of the clients will not affect the id of the $createdClient since there is only one client in the database during this test. It only gets the wrong id assigned once i read it from the db.

I have a siminlar test later on in my testsuite that has the same issue but with an id of 5 instead of 4... So the id when creating the clients in the controller is the correct one (1) but once i try to read the only client in the database it has an id of 4 (or 5 in the next test). Dumping all clients after the post also shows only one database entry with an id of 4 while the redirect is still trying to redirect to an id of 1.

Fairly strange...

FMK's avatar
FMK
OP
Best Answer
Level 4

I found the solution myself. I was returning the result of Client::make([...])->save() as the route parameter, but the result of the save is the result of the action, in this case a boolean true, so it was casted to 1 and resulted in this error. After fixing this the test now runs without a problem!

Please or to participate in this conversation.