运行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
相关产品推荐
相关产品推荐

