如何用PestPHP测试Laravel Passport令牌撤销?遇SQL错误求助
解决Laravel Passport测试登出时的SQL错误(Field 'id' doesn't have a default value)
问题根源
Passport::actingAs()仅用于测试环境模拟用户认证状态,不会在数据库中创建真实的oauth_access_token记录。当登出逻辑调用Auth::user()->token()时,Passport会尝试自动生成新的Token实例,但由于oauth_access_tokens表的id字段是字符串类型主键且无默认值,插入操作因缺少id值触发SQL错误。生产环境正常是因为用户登录时已生成真实token,不存在自动创建的场景。
解决方案
方案一:测试时创建真实的Access Token
在测试中手动生成关联用户的有效token,通过Bearer头发起请求,替代模拟认证:
it('can logout', function () { $this->seed(); $user = User::first(); // 创建密码授权客户端(测试环境需确保存在) $client = \Laravel\Passport\Client::factory()->create(['password_client' => true]); // 生成用户的access token $token = $user->createToken('Test Token', ['*'])->accessToken; $response = $this->withHeaders([ 'Authorization' => 'Bearer ' . $token, ])->postJson('api/v1/logout'); $response ->assertJson([ 'message' => 'Logged out successfully.', ])->assertStatus(200); // 验证token已被撤销 $this->assertDatabaseHas('oauth_access_tokens', [ 'user_id' => $user->id, 'revoked' => true, ]); });
方案二:优化登出逻辑,避免自动创建Token
修改控制器方法,先检查用户是否存在有效token,再执行撤销操作:
public function logout(Request $request): \Illuminate\Http\JsonResponse { $user = $request->user(); if ($user instanceof User) { // 获取用户当前未撤销的token(不自动创建) $token = $user->tokens()->where('revoked', false)->first(); if ($token) { $token->revoke(); return response()->json([ 'message' => 'Logged out successfully.', ], 200); } } return response()->json([ 'message' => 'No active token found.', ], 400); }
注意:使用方案二时,若要测试成功登出分支,仍需在测试中提前为用户创建真实token;若测试无token场景,可调整断言验证400响应。
内容的提问来源于stack exchange,提问作者Diana
相关产品推荐
相关产品推荐

