Laravel Sanctum下assertAuthenticatedAs断言测试异常原因咨询
Laravel Sanctum测试:
assertAuthenticatedAs直接调用失败,带token请求后成功的原因 问题场景
我尝试用assertAuthenticatedAs方法验证用户是否已认证,该方法接收模型实例和guard参数,但直接执行测试时断言失败。
测试代码:
public function test_regsiter_a_user(): void { $existingUsersCount = User::query()->count(); $response = $this->postJson('/api/auth/register', [ 'email' => fake()->safeEmail(), 'name' => fake()->firstName(), 'password' => 'password', 'password_confirmation' => 'password', ]); $this->assertDatabaseCount('users', $existingUsersCount + 1); $this->assertDatabaseCount('personal_access_tokens', 1); $response->assertCreated(); $user = User::query()->where('email', $response->json()['user']['email'])->first(); // $token = $response->json()['token']; // $this->getJson('api/user', headers: [ // 'Authorization' => "Bearer $token" // ])->assertOk(); $this->assertAuthenticatedAs($user, 'sanctum'); }
奇怪的是,取消注释这段带token的请求代码后,assertAuthenticatedAs断言就能通过:
$token = $response->json()['token']; $this->getJson('api/user', headers: [ 'Authorization' => "Bearer $token" ])->assertOk();
注册控制器代码:
public function register(Request $request) { $data = $request->validate([ 'email' => ['required', 'email', 'unique:users,email'], 'name' => ['required'], 'password' => ['required', 'confirmed'], ]); $user = User::query()->create($data)->fresh(); $token = $user->createToken('email'); return response()->json([ 'user' => $user, 'token' => $token->plainTextToken, ], HttpStatus::CREATED->value); }
原因解释
核心逻辑是:assertAuthenticatedAs检查的是当前测试请求上下文的认证状态,而非数据库中是否存在用户的token。
- 注册接口的作用只是创建用户和对应的token凭证,但测试脚本本身的请求上下文并没有通过这个token完成“登录”流程。
assertAuthenticatedAs依赖的是测试进程中Sanctum守卫所持有的已认证用户实例,此时守卫里并没有这个用户。 - 当你发起带
Authorization头的请求时,Sanctum会验证token的有效性,然后在当前测试的上下文里设置认证用户。这时候assertAuthenticatedAs就能检测到守卫中的用户,断言自然通过。
替代方案
如果不想发起额外的API请求,也可以手动让测试上下文的Sanctum守卫认证用户:
$this->actingAs($user, 'sanctum'); $this->assertAuthenticatedAs($user, 'sanctum');
直接调用actingAs方法,指定用户和guard,就能让assertAuthenticatedAs断言通过,无需额外请求。
内容的提问来源于stack exchange,提问作者KWARN KHAM
相关产品推荐
相关产品推荐

