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

Laravel PHPUnit测试:如何触发异常并测试控制器捕获逻辑

测试Laravel控制器store方法的异常处理catch块

问题背景

需要测试控制器store方法中捕获数据库交互异常的catch代码块,确保异常发生时能正确记录日志并返回重定向。

控制器代码

public function store(Request $request, Pipeline $pipeline)
{
    try {
        $request->validate([
            "name" => ["required", "max:512"],
            "stage" => ["required", "in:".Stage::toCSV()],
        ]);

        // 数据库交互逻辑(例如 MyModel::create())

        return response()->json(["message" => trans("round.created")], 201);
    } catch (\Exception $e) {
        Log::error('Exception in MyController@store: ' . $e->getMessage());
        Log::error('Stack trace: ' . $e->getTraceAsString());
        return redirect()->back()->banner(trans('error'));
    }
}

现有尝试的问题

之前的两种mock方式存在误区:

  1. 未确保请求通过验证,导致代码根本没走到数据库交互环节就提前终止
  2. mockException类完全没必要,反而会干扰正常的异常抛出逻辑

正确解决方案

核心要点

  • 必须发送符合验证规则的请求数据,否则会在validate阶段提前抛出异常,无法进入catch块
  • 仅mock模型的create静态方法并抛出异常,无需mockException类
  • 通过断言重定向、会话消息(可选断言日志)验证catch块的执行逻辑

完整测试代码示例

public function test_store_handles_database_exception()
{
    // 1. 准备通过验证的请求数据
    $validRequestData = [
        'name' => '测试名称',
        'stage' => Stage::YOUR_VALID_STAGE, // 替换为符合Stage枚举的有效值
    ];

    // 2. Mock模型的create方法,抛出异常
    $this->partialMock(\App\Models\MyModel::class, function ($mock) use ($validRequestData) {
        $mock->shouldReceive('create')
            ->once()
            ->with($validRequestData) // 可选:验证传入参数的正确性
            ->andThrow(new \Exception('模拟数据库异常'));
    });

    // 3. 可选:禁用真实日志写入,仅断言日志调用次数
    \Illuminate\Support\Facades\Log::shouldReceive('error')->twice();

    // 4. 发送POST请求到store路由
    $response = $this->post(route('your.store.route.name'), $validRequestData);

    // 5. 断言返回重定向
    $response->assertRedirect();
    // 断言会话中存在指定的banner错误消息
    $response->assertSessionHas('banner', trans('error'));
}

关键细节解释

  • partialMock:仅mock指定的create方法,模型的其他方法保持原有逻辑,避免影响其他潜在调用
  • 请求数据必须符合验证规则:确保代码执行到数据库交互环节,才能触发我们模拟的异常
  • 无需mockException:直接抛出真实的Exception实例,就能正常触发catch块中的日志记录和返回逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:11:00