在功能测试 Laravel 应用程序时跳过授权

问题描述 投票:0回答:5

是否有内置方法可以在测试控制器时完全跳过授权?

控制器示例:

public function changePassword(Request $request, LdapInterface $ldap)
{
    $this->authorize('change-password');

    $this->validate($request, [
        'pass' => 'min:8|confirmed|weakpass|required', 
    ]);

    $success = $ldap->updatePassword($request->get('pass'));

    $message = $success ?
        'Your e-mail password has been successfully changed' :
        'An error occured while trying to change your alumni e-mail password.';

    return response()->json(['message' => $message]);
}

我想跳过

change-password
规则,该规则在
AuthServiceProvider
内定义,例如:

public function boot(GateContract $gate)
{
    $gate->define('change-password', function ($user) {
        // Some complex logic here
    });
}

我不想添加 smt。就像代码中的

if (env('APP_ENV') == 'testing') return;
一样。

php laravel-5 phpunit functional-testing
5个回答
7
投票

其实,有一个内置的方法。您可以添加一个在实际授权检查之前调用的

before
回调,并只需返回
true
即可绕过检查:

\Gate::before(function () {
    return true;
});

您应该将此代码段添加到测试的

setUp
方法或您想要绕过授权的每个测试方法中。


5
投票

我不知道有什么,但您可以将该检查移至专用中间件,并使用 withoutMiddleware 特征在测试中禁用它。

或者您可以使用 Mockery 模拟应用程序的门实例。 Mockery 有详细记录,因此我建议阅读文档以获取更多详细信息,但设置它看起来像这样:

$mock = Mockery::mock('Illuminate\Contracts\Auth\Access\Gate');
$mock->shouldReceive('authorize')->with('change-password')->once()->andReturn(true);
$this->app->instance('Illuminate\Contracts\Auth\Access\Gate', $mock);

这将设置一个 Gate 合约的模拟,设置它期望接收的内容以及它应该如何响应,然后将其注入到应用程序中。


5
投票

来自 Laravel 文档 :

在测试您的应用程序时,您可能会发现禁用它很方便 用于某些测试的中间件。这将允许您测试您的 路由和控制器与任何中间件问题隔离。 Laravel 包含一个简单的

WithoutMiddleware
特征,你可以用它来 自动禁用测试类的所有中间件:

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use WithoutMiddleware;

    //
}

或者您可以在测试方法中使用

withoutMiddleware()
方法,如下所示:

public function testBasicExample()
{
    $this->withoutMiddleware();

    $this->visit('/')
         ->see('Laravel 5');
}

PS:从 Laravel 5.1 开始


3
投票

在我的测试中,我添加了一个可以在测试开始时调用的方法,以仅禁用该测试的授权。

添加到您的基础测试类

public function withoutAuthorization()
{
    \Gate::before(function () {
        return true;
    });

    return $this;
}

然后在测试中你可以调用它:

public function testSomeThing()
{
    $this->withoutAuthorization();

    // any gates will be bypassed
    $this->get('/my-protected-endpoint');
}

-5
投票

就简单多了。 只需将其从路由文件中的所需授权部分中取出即可。 在这个例子中,我需要AssignmentsController在没有身份验证的情况下工作,所以我只是将它从jwt.auth组移到了上面:

Route::post('v1/auth/login', 'Api\AuthController@authenticate');
Route::post('v1/auth/sendpassword', 'Api\AuthController@sendPassword');
Route::get('v1/assignments', 'Api\AssignmentsController@getAll');

Route::group(['middleware' => 'jwt.auth'], function() {
  Route::post('v1/auth/logout', 'Api\AuthController@logout');
  Route::post('v1/shipments', 'Api\ShipmentController@getShipments');
  Route::post('v1/assignments/{id}/transfer', 'Api\AssignmentsController@saveAssignment');
  Route::get('v1/shipments/assignments/{assignmentId}', 'Api\AssignmentsController@getDetail');
  Route::post('v1/shipments/assignments/{id}/upload', 'Api\AssignmentsController@uploadFile');
});
© www.soinside.com 2019 - 2024. All rights reserved.