Laravel 7.3单元测试报错:期望状态码200却收到302,求修复方案
登录功能单元测试报错(Expected status code 200 but received 302)解决方法
问题场景
首次使用Laravel 7.3编写登录功能单元测试时,遇到报错:
Expected status code 200 but received 302. Failed asserting that 200 is identical to 302.
需求是:邮箱密码匹配时测试通过,不匹配时返回对应错误提示。
现有代码
测试代码
<?php namespace Tests\Unit; use PHPUnit\Framework\TestCase; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Foundation\Testing\RefreshDatabase; class ExampleTest extends TestCase { use RefreshDatabase; public function user_can_login() { $user = factory(User::class)->create([ 'email' => 'username@example.net', 'password' => 'password', ]); $this->visit('/login'); // Submit form login with email dan password $this->submitForm('Login', [ 'email' => 'username@example.net', 'password' => 'password', ]); // get redirect ke url '/home' (login sukses). $this->seePageIs('/'); } }
路由配置
Route::middleware(['authcheck'])->group(function() { Route::get('/login', 'AuthController@index'); Route::post('/do-login', 'AuthController@doLogin'); });
控制器代码
namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use App\Models\Admin; use App\Models\User; class AuthController extends Controller { public function index() { return view('auth.login'); } public function doLogin(Request $request) { $checkAdmin = User::where('email', $request->email) ->get()->first(); if (!empty($checkAdmin)) { if (Hash::check($request->password, $checkAdmin->password)) { $request->session()->put('auth_user', $checkAdmin); if($checkAdmin->roles == '5'){ return redirect('/list-e-tiket'); }else{ return redirect('/'); } }else{ return redirect('/login')->with('error', 'Password is wrong.!'); } }else{ return redirect('/login')->with('error', 'Username not registered.!'); } } }
问题原因及修正方案
1. 密码哈希不匹配
测试代码中创建用户时直接存入明文密码password,但控制器用Hash::check()验证,该方法要求数据库中是哈希后的密码。需修改用户创建逻辑:
$user = factory(User::class)->create([ 'email' => 'username@example.net', 'password' => Hash::make('password'), // 替换为哈希密码 ]);
2. 中间件逻辑冲突
路由中的authcheck中间件可能逻辑错误,导致未登录用户访问/login时被重定向(返回302)。检查中间件代码,确保未登录用户能正常访问登录页:
// 示例authcheck中间件正确逻辑 public function handle($request, Closure $next) { // 已登录用户跳转到首页,未登录用户允许访问登录页 if ($request->session()->has('auth_user')) { return redirect('/'); } return $next($request); }
3. 测试用例拆分与断言调整
原测试只覆盖了登录成功场景,需拆分测试用例分别验证不同情况:
namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Hash; use App\Models\User; class LoginTest extends TestCase { use RefreshDatabase; // 测试登录成功 public function test_user_can_login_successfully() { $user = User::factory()->create([ 'email' => 'username@example.net', 'password' => Hash::make('password'), 'roles' => '1', // 指定非5角色,确保重定向到/ ]); // 先验证登录页可正常访问 $this->get('/login')->assertStatus(200); // 提交登录请求并验证重定向 $this->post('/do-login', [ 'email' => 'username@example.net', 'password' => 'password', ])->assertRedirect('/'); // 验证session已存入登录用户 $this->assertSessionHas('auth_user'); } // 测试密码错误场景 public function test_user_cannot_login_with_wrong_password() { $user = User::factory()->create([ 'email' => 'username@example.net', 'password' => Hash::make('password'), ]); $response = $this->post('/do-login', [ 'email' => 'username@example.net', 'password' => 'wrong-password', ]); $response->assertRedirect('/login'); $this->assertSessionHas('error', 'Password is wrong.!'); } // 测试邮箱不存在场景 public function test_user_cannot_login_with_non_existent_email() { $response = $this->post('/do-login', [ 'email' => 'not-exist@example.net', 'password' => 'password', ]); $response->assertRedirect('/login'); $this->assertSessionHas('error', 'Username not registered.!'); } }
4. 测试类规范调整
Laravel功能测试应继承Tests\TestCase而非PHPUnit\Framework\TestCase,且建议将测试类放在Tests\Feature目录下,同时引入必要的模型和类(如User、Hash)。
内容的提问来源于stack exchange,提问作者N A K
相关产品推荐
相关产品推荐

