基本上進行簡單的資源讀取/建立/更新/刪除權限測試時應該有兩個測試情境:
如果需要更細緻地去分使用者時,就要做更多不同類型使用者的權限測試:
以對計畫的更新與刪除為例,我們允許計畫擁有者與被邀請成員更新該計畫,但是我們不允許被邀請成員擁有刪除該計畫的權限,所以測試就會增加為(假設使用者都擁有帳號,是被認證過了):
...
use Facades\Tests\Setup\ProjectFactory;
...
/**
*使用者不是計畫擁有者或被邀請成員時,伺服器會回傳403
*@test
*/
public function non_project_related_user_can_not_delete_the_project()
{
$this->signIn();
$project = ProjectFactory::create();
$this->delete(route('project.destory', compact('project')))->assertForbidden();
$this->assertDatabaseHas('projects', ['id' => $project->id]);
}
/**
*使用者是被邀請成員時,伺服器會回傳403
*@test
*/
public function invited_member_can_not_delete_a_project()
{
$owner = factory("App\User")->create();
$project = ProjectFactory::create($owner);
$member = $this->signIn();
$project->invite($member);
$this->delete(route('project.destory', compact('project')))->assertForbidden();
}
/**
*使用者是計畫擁有者時,伺服器會回傳302重定向回index頁面
*@test
*/
public function project_owner_can_delete_the_project()
{
$project = ProjectFactory::ownedBy($this->signIn())->create();
$this->delete(route('project.destory', compact('project')))->assertStatus(302);
$this->assertDatabaseMissing('projects', ['id' => $project->id]);
}
Laracast有介紹可以用Fluent API去設定自己想要的Project的擁有者是誰,或者擁有多少任務等(使用Facades\Tests\Setup\ProjectFactory),特色是最後回傳物件,所以可以產生方法鏈,Laravel中也看到很多這樣的設計:
class ProjectFactory
{
protected $taskCount;
protected $user;
public function ownedBy(User $user)
{
$this->user = $user;
return $this;
}
public function withTasks(int $taskCount)
{
$this->taskCount = $taskCount;
return $this;
}
public function create()
{
$project = factory('App\Project')
->create(['owner_id' => $this->user ?? factory('App\User')]);
if ($this->taskCount) {
factory('App\Task', $this->taskCount)
->create(['project_id' => $project->id]);
}
return $project;
}
}
參考
Laracast