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

运行Laravel测试报错:RequestGuard::attempt方法不存在

解决Laravel测试中RequestGuard::attempt不存在的错误

问题场景

编写了如下Laravel密码修改测试方法:

public function it_can_change_password()
{
    DB::beginTransaction();

    $payloadForUser = [
        "name" => "Name",
        "first_name" => $this->faker->firstName,
        "last_name"  => $this->faker->lastName,
        "email"      => $this->faker->unique()->safeEmail,
        "role_id"    => $this->faker->numberBetween(1, 5),
        "branch_id"  => 1,
        "password" => bcrypt("password")
    ];

    $user = User::create($payloadForUser);

    $credentials = [
        'email' => $user->email,
        'password' => 'password',
        'token_name' => 'admin',
        'api_client' => true,
    ];

    $loginResponse = $this->postJson('api/login', $credentials);
    $loginResponse->assertStatus(200);
    $data = $loginResponse->getData();
    $this->token = $data->token;

    $password = $this->faker->password;

    $payload = [
        'current_password' => "password", # Todo-139
        'new_password' => $password,
        'new_password_confirmation' => $password,
    ];

    $response = $this->postJson('api/user/change/password', $payload, ['Authorization' => 'Bearer ' . $this->token]);
    $response->assertOk();

    $response = $this->postJson('api/logout', [], ['Authorization' => 'Bearer ' . $this->token]);
    $response->assertServerError();

    # Login using old password
    $credentials = [
        'email' => $user->email,
        'password' => 'password',
        'token_name' => 'admin',
        'api_client' => true,
    ];

    $loginResponse = $this->postJson('api/login', $credentials);
    $response->assertServerError();

    # Login using new password
    $credentials = [
        'email' => $user->email,
        'password' => $password,
        'token_name' => 'admin',
        'api_client' => true,
    ];

    $loginResponse = $this->postJson('api/login', $credentials);
    $loginResponse->assertStatus(200);

    DB::rollBack();
}

执行命令php artisan test --filter=it_can_change_password时,最后调用api/login接口的步骤触发错误:

BadMethodCallException: Method Illuminate\Auth\RequestGuard::attempt does not exist. in /vendor/laravel/framework/src/Illuminate/Macroable/Traits/Macroable.php:113

问题原因

错误核心是你的登录逻辑中调用了attempt方法,但当前API认证使用的是RequestGuard(适配token认证的 guard),而attempt是SessionGuard(会话认证)的专属方法,API类型的guard不支持该方法。

解决方案

1. 修正Auth配置文件

打开config/auth.php,确认API guard的驱动配置正确。如果使用Sanctum或Passport做API认证,驱动需对应设置:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'sanctum', // 或 'passport',根据你使用的包调整
        'provider' => 'users',
        'hash' => false,
    ],
],

2. 调整登录接口逻辑

API登录不能用Auth::attempt,需直接验证用户凭证并生成API token。示例登录控制器代码:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use App\Models\User;

public function login(Request $request)
{
    $request->validate([
        'email' => 'required|email',
        'password' => 'required',
        'token_name' => 'required',
    ]);

    $user = User::where('email', $request->email)->first();

    if (! $user || ! Hash::check($request->password, $user->password)) {
        return response()->json(['message' => 'Invalid credentials'], 401);
    }

    // 生成并返回API token
    $token = $user->createToken($request->token_name)->plainTextToken;

    return response()->json(['token' => $token]);
}

3. 修复测试中的变量错误

测试代码里存在变量混淆问题,在“用旧密码登录”的步骤中,错误地使用了$response而非$loginResponse做断言,修正后:

# Login using old password
$credentials = [
    'email' => $user->email,
    'password' => 'password',
    'token_name' => 'admin',
    'api_client' => true,
];

$loginResponse = $this->postJson('api/login', $credentials);
$loginResponse->assertServerError(); // 修正为$loginResponse

内容的提问来源于stack exchange,提问作者Fil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 02:17:55