Summer Sale! All accounts are 50% off this week.

P-James's avatar
Level 12

Authorization Exception Testing VS 403 Status

I've just added a roles and abilities system as detailed here: https://laracasts.com/series/laravel-6-from-scratch/episodes/54

Basically we add a global Gate::before in the AuthServiceProvider boot method, and check for the abilities associated with the Role, and by proxy the User.

public function boot()
    {
        $this->registerPolicies();

        Gate::before(function($user, $ability) {
            if ($user->abilities()->contains($ability)) {
                return true;
            }
        });
    }

HOWEVER, normally in testing I would do assertStatus(403), but now I find myself doing $this->expectException(\Illuminate\Auth\Access\AuthorizationException::class);

Is this a safe workaround? ... it doesn't feel right (yet?). I don't like the the assertion before the code, it also means that particular test is limited to that assertion, so I have to create more tests than I normally would.

Does anyone have any strong views on this? Is there a better way to test-drive this scenario?

See my example below:

/** @test */
    public function gamesCannotBeCreatedByGuests()
    {
        $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $this->actingAs($user);

        $title = 'A random title for the database!';

        $this->expectException(\Illuminate\Auth\Access\AuthorizationException::class);

        $response = $this->post('/games/create', compact('title'));
    }
0 likes
2 replies
P-James's avatar
P-James
OP
Best Answer
Level 12

For anybody reading this, I have just used

$this->post('url', compact('title'))->assertStatus(403);

without saving the response to $response, just stringing on to the get() and it works fine now...

elias's avatar

This is what worked for me

 try {
            $this->get($route);
            $this->fail("$route did not throw an AuthorizationException");
        } catch (\Illuminate\Auth\Access\AuthorizationException $e) {
            $this->assertTrue(true, "$route correctly threw an AuthorizationException");
        }

Please or to participate in this conversation.