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

Laravel 10接口测试验证错误时为何返回302而非400?

问题:Laravel 10中表单验证失败返回302而非400 Bad Request

我在Laravel 10项目中编写了如下测试方法:

public function testAdded()
{
    // Test Data Setup
    $tagModel = Tag::factory()->make([]);  // model only in memory

    // Test Action
    // $tagModel->name = '';
    $response = $this
        ->post(route('tags.store'), $tagModel->toArray());
    $response
        ->assertStatus(201); 

    // READ TAG CREATED ABOVE
    $insertedTag = Tag::getBySearch(search: $tagModel->name, partial: false)
        ->first();

    $this->assertNotNull($insertedTag, 'Inserted tag not found');
    $this->assertEquals(
        $insertedTag->name,
        $tagModel->name,
        'Name read is not equal name on insert'
    );
}

原本测试运行正常,取消注释$tagModel->name = '';后,测试报错:

├ Expected response status code [201] but received 302. 
   ├ Failed asserting that 201 is identical to 302.        
   ├                                                        
   ├ The following errors occurred during the last request:
   ├                                                        
   ├ The name field is required.                           
   │

明明看到验证错误提示,但返回的HTTP状态码是302(临时重定向),而非预期的400 Bad Request。

路由tags.store对应的控制器方法使用自定义的CreateTagRequest类验证,规则如下:

[
    'name' => [
        'required',
        'string',
        'max:100',
    ],
]

控制器方法逻辑:

public function store(CreateTagRequest $request)
{
       try {
        $tag = $this->tagCrudRepository->store(data: $request->only('name'));
        return response()->json(['tag' => (new TagResource($tag))], 201);
    } catch (\Error | \Exception $e) {
        \Log::info($e->getMessage());
        return response()->json([
            'error_message' => $e->getMessage(),
        ], 500);
    }
}

原因与解决方法
  • 核心原因:Laravel默认验证响应逻辑
    Laravel表单请求验证对非AJAX请求默认返回302重定向,将验证错误存入session并跳转回原页面。你的测试请求没有携带AJAX标识头,Laravel判定为普通表单提交,因此返回302。

  • 测试的问题:未模拟AJAX请求
    你的控制器返回JSON响应,说明这是AJAX接口,但测试中没有设置AJAX请求头,导致Laravel触发了普通表单的验证失败逻辑。

  • 解决步骤

    1. 修改测试请求,添加AJAX标识:
      $response = $this
          ->ajax() // 等价于设置X-Requested-With: XMLHttpRequest头
          ->post(route('tags.store'), $tagModel->toArray());
      
    2. 针对验证失败的场景,调整断言逻辑:
      $response->assertStatus(400)
               ->assertJsonValidationErrors('name');
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:18:24