3 votes

Laravel testant l'autorisation à la route, problème d'authentification du middleware

Soyez indulgent avec moi, je suis novice en matière de tests.

Donc, j'ai cette structure actuelle de logiciels intermédiaires :

class IsActive
{
    public function handle($request, Closure $next)
    {
        if (self::active()) {
            return $next($request);
        }
        Auth::guard('web')->logout();
        return redirect('/');
    }

    protected function active()
    {
        if (Auth::guard('web')->check()) {
            $state = Auth::guard('web')->user()->state;
            if ($state == 'enabled') {
                return true;
            }
        }
        return false;
    }
}

class IsAdmin extends IsActive
{
    public function handle($request, Closure $next)
    {
        if (parent::active()) {
            if (Auth::guard('web')->check()) {
                $role = Auth::guard('web')->user()->role->name;
                if ($role == 'admin' || $role == 'superAdmin') {
                    return $next($request);
                }
            }
            return redirect('/');
        }
        Auth::guard('web')->logout();
        return redirect('/');
    }
}

Voici l'itinéraire

Route::group(['middleware' => 'admin'], function () {
    Route::get('/', 'ReportingController@reportingPage');
});
//Its registered on RouteServiceProvider that these routes require IsActive and this specific route needs for the admin

Et dans le Reporting Controller, j'ai obtenu cette fonction

public function reportingPage(Request $request) {
    return view('reporting.reporting');
}

C'est bon jusqu'à présent. Si l'utilisateur a accès, c'est parfait, sinon il est redirigé.

Maintenant pour le test, je veux valider si un administrateur peut le voir (et un non autorisé ne peut pas, mais pour cette question j'essaie de comprendre l'administrateur).

protected $user;

public function setUp()
{
    parent::setUp();
    $this->user = new \App\Models\User(['role_id'    => 6, //admin
                                        'name'       => 'Admin',
                                        'user'       => 'admin',
                                        'email'      => 'admin@admin.com',
                                        'state'      => 'enabled',
                                        'deleted_at' => null]);
    $this->be($this->user);
}

public function testCanAccessReportingPage()
{
    $this->get("/reporting/")->assertStatus(200);
}

Error

Voici l'erreur que j'obtiens et j'essaie de comprendre le processus. Il est évident que je fais quelque chose de mal ou que j'oublie quelque chose, donc les conseils et les idées sur la façon de tester cette autorisation sont très appréciés.

Edit :

Après une réponse supprimée impliquant un peu de refactor et quelques essais, j'ai déterminé que Auth::guard('web')->user() a un utilisateur, Auth::guard('web')->user()->role() est nulle dans l'environnement de test. J'ai résolu le problème en chargeant la relation mais la question que je me pose maintenant est la suivante : Pourquoi cela se produit-il dans l'environnement de test ?

1voto

rkj Points 5200

J'ai changé votre code un peu. J'ai supprimé le code en double et ajouté un chargement paresseux pour le rôle de l'utilisateur. $user->load('role') . Essayez-le

class IsAdmin
{
    public function handle($request, Closure $next)
    {
        //no need to check active again, because you said IsActive is already applied in RouteServiceProvider
        $user = Auth::guard('web')->user();

        $user->load('role'); //lazy eager load

        $role = $user->role->name; 

        if ($role == 'admin' || $role == 'superAdmin') {
            return $next($request);
        }

        Auth::guard('web')->logout();
        return redirect('/');
    }
}

0voto

L'utilisateur créé (mocked) n'est pas utilisé dans le contexte $this.

Si vous regardez la documentation https://laravel.com/docs/5.6/http-tests#session-and-authentication vous voyez la méthode

$this->actingAs($user)

Exemple complet :

<?php

use App\User;

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user)
                         ->withSession(['foo' => 'bar'])
                         ->get('/');
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X