在 Laravel PHPUnit 中测试未经授权的用户限制
Testing unauthorized user restriction in Laravel PHPUnit
Laravel 版本 5.2
在我的项目中,role_id = 4 的用户具有管理员角色,可以管理用户。
我在AuthServiceProvider中定义了以下能力:
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
$gate->define('can-manage-users', function ($user)
{
return $user->role_id == 4;
});
}
我已经在 UserController __construct 方法中使用了这个能力,如下所示:
public function __construct()
{
$this->authorize('can-manage-users');
}
在 ExampleTest 中,我创建了两个测试来检查定义的授权是否有效。
管理员用户的第一个测试 role_id = 4。此测试通过。
public function testAdminCanManageUsers()
{
$user = Auth::loginUsingId(1);
$this->actingAs($user)
->visit('users')
->assertResponseOk();
}
第二个测试是针对另一个没有 role_id = 4 的用户。我已经尝试过响应状态 401 和 403。但是测试失败了:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertResponseStatus(403);
}
失败消息的前几行如下:
A request to [http://localhost/users] failed. Received status code [403].
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:196
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:80
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:61
C:\wamp\www\laravel\blog\tests\ExampleTest.php:33
Caused by exception 'Illuminate\Auth\Access\AuthorizationException'
with message 'This action is unauthorized.' in
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Auth\Access\HandlesAuthorization.php:28
我也试过使用'see'方法如下:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->see('This action is unauthorized.');
}
但它也失败了。我究竟做错了什么?我怎样才能通过测试?
错误是调用了visit
方法。 visit
方法在 InteractsWithPages
特性中。此方法调用 makeRequest
方法,后者又调用 assertPageLoaded
方法。此方法获取返回的状态代码,如果它获取的代码不是 200,它会捕获一个 PHPUnitException
并抛出一个带有消息
的 HttpException
"A request to [{$uri}] failed. Received status code [{$status}]."
这就是测试失败并显示上述消息的原因。
使用get
方法代替visit
方法可以顺利通过测试。例如:
public function testNonAdminCannotManageUsers()
{
$user = App\User::where('role_id', '<>', 4)->first();
$this->actingAs($user)
->get('users')
->assertResponseStatus(403);
}
此测试将通过并确认非管理员用户无法访问 url。
由于 Auth
中间件在默认情况下未经身份验证时会重定向到登录路由,您还可以执行以下测试:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertRedirect('login');
}
至少从 Laravel 5.4 开始,您将需要使用 assertStatus(403)
方法。
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertStatus(403);
}
Laravel 版本 5.2
在我的项目中,role_id = 4 的用户具有管理员角色,可以管理用户。
我在AuthServiceProvider中定义了以下能力:
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
$gate->define('can-manage-users', function ($user)
{
return $user->role_id == 4;
});
}
我已经在 UserController __construct 方法中使用了这个能力,如下所示:
public function __construct()
{
$this->authorize('can-manage-users');
}
在 ExampleTest 中,我创建了两个测试来检查定义的授权是否有效。
管理员用户的第一个测试 role_id = 4。此测试通过。
public function testAdminCanManageUsers()
{
$user = Auth::loginUsingId(1);
$this->actingAs($user)
->visit('users')
->assertResponseOk();
}
第二个测试是针对另一个没有 role_id = 4 的用户。我已经尝试过响应状态 401 和 403。但是测试失败了:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertResponseStatus(403);
}
失败消息的前几行如下:
A request to [http://localhost/users] failed. Received status code [403].
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:196 C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:80 C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:61 C:\wamp\www\laravel\blog\tests\ExampleTest.php:33
Caused by exception 'Illuminate\Auth\Access\AuthorizationException' with message 'This action is unauthorized.' in C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Auth\Access\HandlesAuthorization.php:28
我也试过使用'see'方法如下:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->see('This action is unauthorized.');
}
但它也失败了。我究竟做错了什么?我怎样才能通过测试?
错误是调用了visit
方法。 visit
方法在 InteractsWithPages
特性中。此方法调用 makeRequest
方法,后者又调用 assertPageLoaded
方法。此方法获取返回的状态代码,如果它获取的代码不是 200,它会捕获一个 PHPUnitException
并抛出一个带有消息
HttpException
"A request to [{$uri}] failed. Received status code [{$status}]."
这就是测试失败并显示上述消息的原因。
使用get
方法代替visit
方法可以顺利通过测试。例如:
public function testNonAdminCannotManageUsers()
{
$user = App\User::where('role_id', '<>', 4)->first();
$this->actingAs($user)
->get('users')
->assertResponseStatus(403);
}
此测试将通过并确认非管理员用户无法访问 url。
由于 Auth
中间件在默认情况下未经身份验证时会重定向到登录路由,您还可以执行以下测试:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertRedirect('login');
}
至少从 Laravel 5.4 开始,您将需要使用 assertStatus(403)
方法。
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertStatus(403);
}