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

Laravel 9.x自动化测试状态码异常:预期422却返回302

Laravel 9.x自动化测试:预期422却返回302的问题排查

在Laravel 9.x环境下执行自动化测试时,遇到一个问题:测试用例预期接口返回422(HTTP_UNPROCESSABLE_ENTITY)状态码,但实际返回302。测试环境响应错误,但应用正常运行时返回的响应符合预期。

测试代码(CategoryTest.php)

class CategoryTest extends TestCase {
    use RefreshDatabase;

    ...

    public function test_categories_cannot_create_without_payload_should_receive_422() {
        $response = $this->post(route('categories.store'), []);

        $response->assertStatus(Response::HTTP_UNPROCESSABLE_ENTITY);
        $response->assertJson([
            'message',
            'errors',
        ]);
    }

    ...
}

全局FormRequest类代码

namespace App\Http\Requests;

use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class FormRequest extends \Illuminate\Foundation\Http\FormRequest {
    protected function failedValidation(Validator $validator) {
        if ($this->expectsJson()) {
            throw new HttpResponseException(
                response()->json([
                    'message' => 'Please check the following error(s)',
                    'errors'  => (new ValidationException($validator))->errors(),
                ], Response::HTTP_UNPROCESSABLE_ENTITY)
            );
        }

        parent::failedValidation($validator);
    }
}

问题原因

核心问题在于expectsJson()方法的判断逻辑:

  • 应用正常运行时,前端请求通常会携带Accept: application/json请求头,此时expectsJson()返回true,触发自定义的JSON格式错误响应,返回422状态码。
  • 测试代码中使用的post方法默认不会添加Accept: application/json头,导致expectsJson()返回false,执行父类的failedValidation方法——Laravel默认对非JSON请求的验证失败会返回302重定向(重定向到之前的页面),所以测试得到302状态码。

解决方案

有两种方式可以解决这个问题:

方案一:手动添加Accept请求头

在测试的post请求中,明确添加Accept: application/json头,告知后端期望JSON响应:

$response = $this->post(route('categories.store'), [], ['Accept' => 'application/json']);

方案二:使用postJson方法

Laravel提供了postJson方法,该方法会自动设置Accept: application/json请求头,简化测试代码:

$response = $this->postJson(route('categories.store'), []);

修改测试代码后,expectsJson()会返回true,触发自定义的JSON错误响应,测试即可得到预期的422状态码。

内容的提问来源于stack exchange,提问作者Mr.Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:25:02