Laravel Nova测试如何避免重定向,直接验证页面存在?
Laravel Nova 页面存在性测试:绕过认证与权限校验问题
我正在给Laravel Nova Admin应用添加Pest和单元测试,只想验证页面是否存在,完全不想考虑用户认证、角色或权限这些条件。但测试Nova路由时总是被重定向到登录页,试过移除部分中间件、模拟授权用户都没用——前者返回302重定向到登录页,后者直接403禁止访问。怎么才能禁用重定向、绕过所有权限认证,直接测试页面内容?
失败的测试尝试1
class ExampleTest extends TestCase { public function test_it_should_have_a_login_page() { $response = $this->get('/login'); $response->assertStatus(200); //<-- 这个测试通过 } public function test_it_should_have_a_routing_resources_page() { $response = $this ->withoutMiddleware(\App\Http\Middleware\Authenticate::class) ->withoutMiddleware(\App\Http\Middleware\RedirectIfAuthenticated::class) ->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class) ->get('/resources/routing'); $response->assertStatus(200); //<-- 失败,返回302重定向到登录页 } }
失败的测试尝试2
public function test_it_should_have_a_routing_resources_page() { $user = User::factory()->create(); $role = NovaRole::create(['name' => 'admin', 'updated_at' => now(), 'created_at' => now(), 'slug' => 'admin']); $user->assignRole($role->name); $permissions = config('nova-permissions.permissions'); foreach ($permissions as $permission) { $user->hasPermissionTo($permission); } $response = $this ->actingAs($user) ->withoutMiddleware(\App\Http\Middleware\Authenticate::class) ->withoutMiddleware(\App\Http\Middleware\RedirectIfAuthenticated::class) ->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class) ->get('/resources/routing'); $response->assertStatus(200); //<-- 失败,返回403禁止访问 }
解决方案
Laravel Nova自身带有独立的中间件和授权控制,只移除应用层的中间件没用,得从Nova的核心校验入手:
1. 绕过Nova的认证中间件
Nova路由使用的是Laravel\Nova\Http\Middleware\Authenticate,而非你应用自定义的认证中间件,所以要移除这个Nova自带的中间件:
public function test_it_should_have_a_routing_resources_page() { $response = $this ->withoutMiddleware(\Laravel\Nova\Http\Middleware\Authenticate::class) ->get('/resources/routing'); $response->assertStatus(200); }
2. 绕过Nova的权限校验(资源策略)
如果仍返回403,说明Nova的资源授权策略在生效。可以通过两种方式绕过:
全局禁用所有授权校验
在测试方法开头调用$this->withoutAuthorization();,这会绕过Laravel所有授权逻辑,包括Nova的资源策略:
public function test_it_should_have_a_routing_resources_page() { $this->withoutAuthorization(); $this->withoutMiddleware(\Laravel\Nova\Http\Middleware\Authenticate::class); $response = $this->get('/resources/routing'); $response->assertStatus(200); }
针对特定资源Mock策略校验
如果不想全局禁用授权,可单独Mock对应资源的策略类,让权限校验返回true:
use App\Nova\Routing; use App\Policies\RoutingPolicy; public function test_it_should_have_a_routing_resources_page() { $this->withoutMiddleware(\Laravel\Nova\Http\Middleware\Authenticate::class); $this->mock(RoutingPolicy::class, function ($mock) { // 针对列表页,需要mock viewAny方法 $mock->shouldReceive('viewAny')->andReturn(true); // 若测试详情页,需额外mock view方法,依此类推 }); $response = $this->get('/resources/routing'); $response->assertStatus(200); }
3. 移除Nova的其他校验中间件(可选)
如果还有Nova的Authorize中间件干扰,可一并移除:
public function test_it_should_have_a_routing_resources_page() { $response = $this ->withoutMiddleware([ \Laravel\Nova\Http\Middleware\Authenticate::class, \Laravel\Nova\Http\Middleware\Authorize::class, ]) ->get('/resources/routing'); $response->assertStatus(200); }
内容的提问来源于stack exchange,提问作者Asa LeHolland
相关产品推荐
相关产品推荐

