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

如何编写测试验证Laravel模型事务方法异常时进入catch触发回滚

解决方案

错误原因排查

你遇到的BadMethodCallException报错,核心原因是你错误地Mock了目标测试方法addRecord所属的MyModel全类,导致原类的addRecord静态方法被Mock覆盖不存在了。你需要测试的就是addRecord本身的逻辑,因此不要Mock这个方法,仅需要Mock它依赖的create方法和DB事务操作即可。

另外先修正你的业务代码笔误:catch块捕获的异常变量是$ex,你抛出的是未定义的$e,需要改为:

catch (\Exception $ex) {
    DB::rollback();
    throw $ex;
}

测试代码实现

基于Laravel官方测试规范,你可以通过Facade监听、模型静态方法Mock来实现需求:

public function test_add_record_rollback_on_exception()
{
    // 监听DB事务操作,断言调用符合预期
    \DB::shouldReceive('beginTransaction')->once();
    \DB::shouldReceive('rollback')->once(); // 核心断言:失败时rollback必须被调用
    \DB::shouldReceive('commit')->never(); // 核心断言:失败时commit绝对不能被调用

    // Mock MyModel的create方法,调用时直接抛出异常,模拟try块失败场景
    \App\Models\MyModel::shouldReceive('create')
        ->once()
        ->andThrow(new \Exception('模拟create失败'));

    // 断言方法会正常抛出异常
    $this->expectException(\Exception::class);

    // 执行实际要测试的业务方法
    \App\Models\MyModel::addRecord();
}

逻辑说明

  • 我们只MockMyModel::create这个依赖方法,保留原addRecord的所有逻辑,确保测试的是真实业务流程
  • 通过DB Facade的调用断言,直接验证事务回滚逻辑是否触发,完全匹配你的测试需求
  • 不需要额外处理事务上下文,Mock的逻辑完全隔离了数据库操作,测试可以快速运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 23:09:02