You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 07:40:20