Laravel测试授权路由,中间件认证问题

5
请跟着我一起学习测试,我还不是很熟练。 现在,我有这样一组中间件结构:
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('/');
    }
}

这是路由。
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

在报告控制器中,我得到了这个函数。
public function reportingPage(Request $request) {
    return view('reporting.reporting');
}

到目前为止非常好。如果用户有权限,很好,如果没有权限,它会被重定向。

现在进行测试,我想验证管理员是否可以查看它(未经授权的不能,但对于这个问题,我正在尝试弄清楚管理员)

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

这是我收到的错误信息,我正在尝试找出问题所在。显然我做错了什么或者忘记了某些东西,所以非常感谢有关如何测试此授权的提示和想法。
编辑:
在一个回答被删除后涉及一些重构和尝试之后,我已经确定Auth::guard('web')->user()有一个用户,但是Auth::guard('web')->user()->role()在测试环境中为null。我通过加载关系来解决了这个问题,但我现在的问题是:为什么会在测试环境中发生这种情况。

1
你正在创建用户并将其设置为会话用户。当我们创建用户时,它不会加载关系。在创建用户之后,如果您加载用户 $user = User::find(1); 然后将其设置为会话用户,则可以访问 Auth::user()->role。或者使用惰性贪婪加载 Auth::user()->load('role') 加载它。 - rkj
2个回答

3

可能创建的用户(模拟)在此上下文中未被使用。

如果您查看文档https://laravel.com/docs/5.6/http-tests#session-and-authentication,您会看到方法

$this->actingAs($user)

完整示例:

<?php

use App\User;

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

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

我已经确定了我的编辑问题,目前我正在寻找为什么会发生这种情况的答案。 - abr
你应该像这样创建虚假关系:$user = factory(User::class)->create(); $post= factory(Post::class)->create(['user_id' => $user->id]); - Andrey Krasilnikov

1
我已经稍微更改了你的代码。删除了重复的代码,并为用户角色添加了懒惰贪婪加载$user->load('role')。试一下吧。
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('/');
    }
}

你有检查过,在那里获取到了 $user 实例吗?同时也要检查我是否已经使用预加载 role。尝试打印出它。 - rkj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接