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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 19:39:56