是否有内置方法可以在测试控制器时完全跳过授权?
控制器示例:
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;
一样。
其实,有一个内置的方法。您可以添加一个在实际授权检查之前调用的
before
回调,并只需返回 true
即可绕过检查:
\Gate::before(function () {
return true;
});
您应该将此代码段添加到测试的
setUp
方法或您想要绕过授权的每个测试方法中。
我不知道有什么,但您可以将该检查移至专用中间件,并使用 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 合约的模拟,设置它期望接收的内容以及它应该如何响应,然后将其注入到应用程序中。
来自 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 开始
在我的测试中,我添加了一个可以在测试开始时调用的方法,以仅禁用该测试的授权。
添加到您的基础测试类
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');
}
就简单多了。 只需将其从路由文件中的所需授权部分中取出即可。 在这个例子中,我需要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');
});