【问题标题】:Laravel Unit Testing Disable Policie / Error: This action is unauthorizedLaravel 单元测试禁用策略/错误:此操作未经授权
【发布时间】: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


    【解决方案1】:

    问题已解决:

    Auth::setUser($user = m::mock(User::class));
    $user->shouldReceive('hasPermissionTo')->andReturn(true);
    

    就这么简单..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-04
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      相关资源
      最近更新 更多