在测试Laravel应用程序时,一个加载门是如何定义的?

问题描述:

我正在为Laravel应用程序编写测试。在我的AuthServiceProvider->boot()中,我根据数据库中的权限表定义了许多用户能力$gate->define()在测试Laravel应用程序时,一个加载门是如何定义的?

基本上这样的:

foreach ($this->getPermissions() as $permission) { 
      $gate->define($permission->name, function ($user) use ($permission) { 
       return $user->hasPermission($permission->name); 
      }); 
     } 

在我的测试,我动态创建的权限,但AuthServiceProvider已经启动了,这意味着我无法验证与@canGate等用户权限

有没有适当的方法来处理这个问题?

你可以做这样的事情里面AuthServiceProvider

首先导入必要的软件包

use Illuminate\Auth\Access\Gate; 
use Illuminate\Contracts\Auth\Access\Gate as GateContract; 
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; 

,然后添加此boot()方法

public function boot(GateContract $gate) 
{ 
    parent::registerPolicies($gate); 

    $gate->define('update-post', function ($user, $post, $isModerator) { 
     // check if user id equals post user id or whatever 
     if ($user->id === $post->user->id) { 
      return true; 
     } 

     // you can define multiple ifs 
     if ($user->id === $category->user_id) { 
      return true; 
     } 

     if ($isModerator) { 
      return true; 
     } 

     return false; 
    }); 

    // you can also define multiple gates 
    $gate->define('update-sub', function($user, $subreddit) { 
     if($user->id === $subreddit->user->id) { 
      return true; 
     } 

     return false; 
    }); 

然后在你的控制器,你可以做些什么像这样

if (Gate::denies('update-post', [$post, $isModerator])) { 
    // do something 
} 

public function boot(GateContract $gate) 
{ 
    parent::registerPolicies($gate); 

    $gate->before(function($user, $ability) use ($gate){ 
     return $user->hasPermission($ability); 
    }); 
} 

我还没有广泛地测试过这个,但它似乎从我的快速测试工作。

+0

如果您想要在插入权限后在testMethod中注册策略,该怎么办? –

我知道我对这场比赛有点晚了,但仍然 - 我自己也有同样的问题,因此这个问题没有一个全面的答案,这里是我对同一问题的解决方案(在Laravel 5.3):

我在我的app\Providers\AuthServiceProvider得到这个:

/** 
* Register any authentication/authorization services. 
* 
* @param Gate $gate 
*/ 
public function boot(Gate $gate) 
{ 
    $this->registerPolicies(); 

    if (!app()->runningInConsole()) { 
     $this->definePermissions($gate); 
    } 
} 

/** 
* @param Gate $gate 
*/ 
private function definePermissions(Gate $gate) 
{ 
    $permissions = Permission::with('roles')->get(); 

    foreach($permissions as $permission) { 
     $gate->define($permission->key, function($user) use ($permission) { 
      return $user->hasRole($permission->roles); 
     }); 
    } 
} 

这需要正常的应用程序流的照顾时检测和禁用过早政策登记测试。

在我tests/TestCase.php文件我已经定义了以下方法(注意:GateIlluminate\Contracts\Auth\Access\Gate):

/** 
* Logs a user in with specified permission(s). 
* 
* @param $permissions 
* @return mixed|null 
*/ 
public function loginWithPermission($permissions) 
{ 
    $user = $this->userWithPermissions($permissions); 

    $this->definePermissions(); 

    $this->actingAs($user); 

    return $user; 
} 

/** 
* Create user with permissions. 
* 
* @param $permissions 
* @param null $user 
* @return mixed|null 
*/ 
private function userWithPermissions($permissions, $user = null) 
{ 
    if(is_string($permissions)) { 
     $permission = factory(Permission::class)->create(['key'=>$permissions, 'label'=>ucwords(str_replace('_', ' ', $permissions))]); 

     if (!$user) { 
      $role = factory(Role::class)->create(['key'=>'role', 'label'=>'Site Role']); 

      $user = factory(User::class)->create(); 
      $user->assignRole($role); 
     } else { 
      $role = $user->roles->first(); 
     } 

     $role->givePermissionTo($permission); 
    } else { 
     foreach($permissions as $permission) { 
      $user = $this->userWithPermissions($permission, $user); 
     } 
    } 

    return $user; 
} 

/** 
* Registers defined permissions. 
*/ 
private function definePermissions() 
{ 
    $gate = $this->app->make(Gate::class); 
    $permissions = Permission::with('roles')->get(); 

    foreach($permissions as $permission) { 
     $gate->define($permission->key, function($user) use ($permission) { 
      return $user->hasRole($permission->roles); 
     }); 
    } 
} 

这使我在以多种方式测试使用此。考虑我的tests/integration/PermissionsTest.php文件中的用例:

/** @test */ 
public function resource_is_only_visible_for_those_with_view_permission() 
{ 
    $this->loginWithPermission('view_users'); 
    $this->visit(route('dashboard'))->seeLink('Users', route('users.index')); 
    $this->visit(route('users.index'))->assertResponseOk(); 

    $this->actingAs(factory(User::class)->create()); 
    $this->visit(route('dashboard'))->dontSeeLink('Users', route('users.index')); 
    $this->get(route('users.index'))->assertResponseStatus(403); 
} 

/** @test */ 
public function resource_action_is_only_visible_for_those_with_relevant_permissions() 
{ 
    $this->loginWithPermission(['view_users', 'edit_users']); 
    $this->visit(route('users.index'))->seeLink('Edit', route('users.edit', User::first()->id)); 

    $this->loginWithPermission('view_users'); 
    $this->visit(route('users.index'))->dontSeeLink('Edit', route('users.edit', User::first()->id)); 
} 

这在我所有的测试中都能正常工作。我希望它有帮助。