zufflie's avatar

Laravel Pest Test fails when run together, but pass when alone

Hey Guys. I watched Pest Driven Laravel and wanted to implement it in my own personal Project.

I have a weird error which i can not get around. I have a Backend Part in Routes, shielded by the these middlewares:

Route::middleware(['auth:sanctum', config('jetstream.auth_session'), Admin::class])

Admin::class is just checking.

 if (! Auth::user()->isAdmin()) {
            return redirect('login');
        }

atm it is not pretty, but it works no problem in the frontend. Now i want to create some FAQs.

My test look like this:

it('displays the edit FAQ page to admin', function () {
    asAdmin();

    $faq = Faq::factory()->create();

    get(route('backend.faqs.edit', ['faq' => $faq->id]))
        ->assertOk()
        ->assertSee($faq->question);
});

And my Pest.php like this:

function asAdmin() {
    $adminRole = Role::firstOrCreate(['id' => 1, 'title' => 'admin']);
    $user = User::factory()->create();
    $user->roles()->attach($adminRole->id);

    test()->actingAs($user);

    return $user;
}

ofc.

    Tests\TestCase::class,
    Illuminate\Foundation\Testing\RefreshDatabase::class,
)->in('Feature');

Refreshdatabase is on.

When i run the test alone it works fine, if i run them together like ./vendor/bin/pest the first one passes, the rest fails. So i guess when i do this function once, it is somehow exhausted. Could someone help me explain this behavior?

0 likes
6 replies
LaryAI's avatar
Level 58

It sounds like you're encountering a common issue with state leakage between tests when running your test suite as a whole. This can happen when the state of the application is not completely reset between tests, leading to unexpected behavior.

Since you're using the RefreshDatabase trait, your database should be reset between each test. However, there might be other application state that is not being reset, such as cached configurations or in-memory data.

Here are a few things you can try to resolve this issue:

  1. Ensure that the RefreshDatabase trait is being applied to each test. You can do this by including it in the Pest.php file or in a base test class that all your tests extend.

  2. Reset the application state after each test. You can do this by calling Artisan::call('config:clear') and Artisan::call('cache:clear') after each test or in a tearDown method.

  3. Make sure that your asAdmin helper function is not causing any side effects that persist between tests. For example, if the Role::firstOrCreate method is caching the role, it might not be created again in subsequent tests.

Here's an example of how you might modify your asAdmin function to ensure it's not causing state leakage:

function asAdmin() {
    // Clear the roles cache if necessary
    // Role::flushEventListeners();

    $adminRole = Role::firstOrCreate(['id' => 1, 'title' => 'admin']);
    $user = User::factory()->create();
    $user->roles()->attach($adminRole->id);

    test()->actingAs($user);

    return $user;
}

And here's an example of how you might reset the application state after each test in your Pest.php file:

afterEach(function () {
    // Reset the application state
    Artisan::call('config:clear');
    Artisan::call('cache:clear');
});

Remember to import the necessary classes at the top of your Pest.php file:

use Illuminate\Support\Facades\Artisan;

Try these suggestions and see if they help your tests pass consistently when run together. If the problem persists, you may need to look more closely at the specific tests that are failing to identify any other shared state that could be causing the issue.

zufflie's avatar

Also after running X tests, it wont do anything anymore. It just stales after running the first Test Unit Test.

Visp's avatar

Has anyone found a solution to this problem? I want to use Pest in my projects, but this problem prevents me from using it and I can't find the solution (apart from going back to PHPUnit).

zufflie's avatar

@Visp Hey Visp. Sadly i cant really help you, at the end it was a problem on my computer side. I switched to a macbook pro after i had a Thinkpad T460 with Arch Linux (what a weird switch from that to macbook) and everything runs smoothly and as intended.

Visp's avatar

Better late than never.... This error can be fixed if you replace in your route file require_once by require.

2 likes
Shafqat_ali's avatar

@visp. My God, you are a life saver. I have been banging my head to figure out what was wrong. This simple change actually have solved my problem.

Please or to participate in this conversation.