【发布时间】:2018-02-13 12:40:56
【问题描述】:
我是 Laravel 的新手,这是我的第一个应用程序。在阅读了很多关于 Laravel 单元测试的文章后,我决定开发自己的。
我有一个如下所示的控制器:
public function edit($id)
{
$project = $this->projectRepository->getById($id);
$types = $this->typeRepository->getAll();
$thematics = $this->thematicRepository->getAll();
$this->authorize('manage',$project);
return view('project.edit',compact(['project','thematics','types']));
}
目的是显示用于项目编辑的表单。问题在于这一行:$this->authorize('manage',$project); 指的是这个政策:
<?php
namespace App\Policies;
use App\Models\Project;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class ProjectPolicy extends Policy
{
use HandlesAuthorization;
/**
* Determine whether the user can manage the project.
*
* Request made with Eloquent
*
* @param \App\Models\User $user
* @param \App\Models\Project $project
* @return mixed
*/
public function manage(User $user, Project $project)
{
return $user->project->contains($project->id);
}
}
实际上,当我尝试测试控制器的编辑方法时,我得到:
Tests\Unit\Http\Controllers\ProjectControllerTest::test_edit_project Illuminate\Auth\Access\AuthorizationException:此操作是 未经授权。
我的测试如下所示:
<?php
namespace Tests\Unit\Http\Controllers;
use App\Http\Controllers\ProjectController;
use App\Http\Requests\ProjectCreateRequest;
use App\Models\Project;
use App\Repositories\ProjectRepository;
use App\Repositories\ThematicRepository;
use App\Repositories\TypeRepository;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Database\Connection;
use Symfony\Component\HttpFoundation\ParameterBag;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\ControllerTestCase;
use Mockery as m;
use Gate;
use Illuminate\Foundation\Testing\WithoutMiddleware;
class ProjectControllerTest extends ControllerTestCase
{
use DatabaseTransactions;
use WithoutMiddleware;
/**
* @var \App\Repositories\ProjectRepository
* @var \App\Repositories\ThematicRepository
* @var \App\Repositories\TypeRepository
* @var \App\Models\Project
* @var \Mockery\Mock
*/
protected $projectRepoMock;
protected $thematicRepoMock;
protected $typeRepoMock;
protected $projectMock;
protected $db;
public function setUp()
{
$this->afterApplicationCreated(function () {
$this->db = m::mock(
Connection::class.'[select,update,insert,delete]',
[m::mock(\PDO::class)]
);
$manager = $this->app['db'];
$manager->setDefaultConnection('mock');
$r = new \ReflectionClass($manager);
$p = $r->getProperty('connections');
$p->setAccessible(true);
$list = $p->getValue($manager);
$list['mock'] = $this->db;
$p->setValue($manager, $list);
$this->projectRepoMock = m::mock(ProjectRepository::class);
$this->thematicRepoMock = m::mock(ThematicRepository::class);
$this->typeRepoMock = m::mock(TypeRepository::class);
$this->projectMock = m::mock(Project::class . '[update, delete]');
});
parent::setUp();
}
public function test_edit_project()
{
$projectInfo = [
'thematic_id' => 1,
'type_id' => 1,
'state_id' => 1,
'entity_id' => 1,
'application_max' => 3,
'title' => 'Ceci est un titre de projet',
'description' => 'Ceci est une description de projet',
'deliverable' => 'Ceci est un livrable de projet',
'context' => 'Ceici est un contexte de projet',
'topic' => 'Ceci est une problématique de projet',
'technical_constraint' => 'Contraintes techniques',
'financial_constraint' => 'Contraintes financières',
'time_constraint' => 'Contraintes temporelles'
];
$project = new Project($projectInfo);
$controller = new ProjectController($this->projectRepoMock,$this->thematicRepoMock,$this->typeRepoMock);
$this->thematicRepoMock->shouldReceive('getAll')->once();
$this->typeRepoMock->shouldReceive('getAll')->once();
$types = $this->typeRepoMock->getAll();
$thematics = $this->thematicRepoMock->getAll();
$this->thematicRepoMock->shouldReceive('getAll')->once()->andReturn($thematics);
$this->typeRepoMock->shouldReceive('getAll')->once()->andReturn($types);
$this->projectRepoMock->shouldReceive('getById')
->once()
->with($project->id)
->andReturn($project);
$view = $controller->edit($project->id);
$this->assertEquals('project.edit', $view->getName());
$this->assertArraySubset(['project' => $project], $view->getData());
$this->assertArraySubset(['types' => $types], $view->getData());
$this->assertArraySubset(['thematics' => $thematics], $view->getData());
}
我尝试了很多事情,但没有成功。其中之一是使用:
$this->withoutMiddleware();
关于如何禁用测试策略的任何想法?
【问题讨论】:
标签: php unit-testing laravel-5.5