AlbertMulaki's avatar

How can i test that the authorize method has authorized the user to do the request.

How can i test that the authorize method has authorized the user to do the request, and check if this function has been called.

I have about 7 roles:

$roles = [
    'SuperAdmin',
    'Admin',
    'MediaAdmin',
    'InstitutionAdmin',
    'DataEntryUser',
    'ViewOne',
    'ViewAll'
];

Right now i do something like this:

    public function test_super_admin_can_create_a_patient()
    {
        $this->signInAsSuperAdmin();

        $this->post(action('ChildrensController@store'), $this->childForm);

        $this->performAssertsForThisForm();
    }

    public function test_admin_can_create_a_patient()
    {
        $this->signInAsAdmin();

        $this->post(action('ChildrensController@store'), $this->childForm);

        $this->performAssertsForThisForm();
    }

    public function test_view_one_user_cannot_create_a_patient()
    {
        $this->withExceptionHandling();

        $this->signInAsViewOneUser();

        $this->post(action('ChildrensController@store'), $this->childForm)
            ->assertStatus(403);
    }

   ...

for every role. I wonder if this is the best approach. Also it would be nice if i could just test the policy like this:

   /** @test */
    public function authorized_users_can_create_a_media()
    {
        $mediaPolicy = new MediaPolicy();

        $userTypes = [
            'SuperAdmin',
            'Admin',
            'MediaUser',
            'InstitutionAdmin',
        ];

        foreach($userTypes as $userType){
            $this->assertTrue($mediaPolicy->create(create('App\Entities\User', ['UserType' => $userType])));
        }
    }

And then with some kind of mocking or without mocking, assert that the authorize function has been called, with the can do thing:

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return $this->user()->can('create', Media::class); // this function right here has been called. 
    }

I think that this would be better, but i may be wrong. Do you have any experience about this type of testing?

by doing like i did it doesnt feel i am doing it well, and the number of tests i have to write is too much i think. 7 roles * 4 crud operations = 28 tests just for some crud operations, and nothing more. I appreciate your help. thanks.

0 likes
3 replies
martinbean's avatar
Level 80

@AlbertMulaki If you’re trying to test the same functionality, but with different users and different expectations based on their role, then you could use a data provider in your test:

/**
 * @dataProvider usersProvider
 */
public function testCreatingSomething($role, $expected)
{
    $this->signInWithRole($role);

    $response = $this->doSomething();

    if ($expected) {
        $response->assertSuccessful();
    } else {
        $response->assertUnauthori();
    }
}

public function usersProvider()
{
    return [
        ['SuperAdmin', true],
        ['Admin', true],
        ['MediaUser', false],
        ['InstitutionAdmin', false],
    ];
}

This will call your testCreatingSomething() method with each array item’s values as method parameters.

1 like
AlbertMulaki's avatar

@martinbean thank you very much, i think this will do the job, thanks a lot four your help. This is exactly what i needed, i cant thank you much enough, thank you very much.

1 like

Please or to participate in this conversation.