normykinz's avatar

Intermittent authorization test failiure.

I wonder if anyone can shed some light on this. I have a test that seems to fail randomly and I can't figure out why.

Test

it('allows a user to edit only their own details', function () {
    $user1 = User::factory()->create();
    $user2 = User::factory()->create();

    actingAs($user1);

    expect(get('profile/' . $user2->id))->toHaveStatus(Response::HTTP_FORBIDDEN);
});

Route

Route::get('profile/{user}', [UserController::class, 'edit'])
    ->name('user.edit')
    ->middleware(['auth', 'verified'])
    ->can('update', 'user');

Policy

public function view(User $user, User $model): bool
{
	return $user === $model;
}

Random failed result

Expected response status code [403] but received 200.

Fails approximately 20% of the time. I've tried using auth()->logout() in the beforeEach callback with no success.

0 likes
1 reply
LaryAI's avatar
Level 58

The issue might be related to the fact that the test is not clearing the authenticated user between runs. One solution could be to use the refreshApplication method before each test to ensure a clean slate. Here's an example:

public function setUp(): void
{
    parent::setUp();

    $this->refreshApplication();
}

it('allows a user to edit only their own details', function () {
    $user1 = User::factory()->create();
    $user2 = User::factory()->create();

    actingAs($user1);

    expect(get('profile/' . $user2->id))->toHaveStatus(Response::HTTP_FORBIDDEN);
});

Alternatively, you could try using the withoutMiddleware method to disable the auth and verified middleware for this test:

it('allows a user to edit only their own details', function () {
    $user1 = User::factory()->create();
    $user2 = User::factory()->create();

    $this->withoutMiddleware(['auth', 'verified']);

    actingAs($user1);

    expect(get('profile/' . $user2->id))->toHaveStatus(Response::HTTP_FORBIDDEN);
});

Please or to participate in this conversation.