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

Laravel PHPUnit中如何Mock模型多层关联的属性返回值

问题根因

with()是Eloquent ORM查询阶段的预加载方法,仅对模型查询构造器生效。你通过app(Check::class)拿到的是空白Check模型实例,没有执行数据库查询,无法通过with()挂载关联。
直接实例化的模型默认关联属性为null,会命中业务代码中if (!$user = $check->user)的判断直接返回false,走不到后续读取some_id的逻辑。

正确实现方式

不需要在Mock逻辑中调用with(),直接构建好带完整关联链的模型实例,传入andReturn()即可,两种常用实现:

方案1:手动设置关联(无额外依赖,逻辑直观)

从最内层关联开始逐层实例化模型,通过setRelation()方法挂载关联,Eloquent访问关联时如果检测到关联已被设置,会直接返回对应实例,不会触发数据库查询:

$app->bind(Service::class, function () {
    return $this->mock(Service::class, function(MockInterface $mock) {
        $mock->makePartial();

        // 构建最内层verification模型,设置目标属性
        $verification = new Verification();
        $verification->some_id = 123; // 替换为测试需要的具体值

        // 构建user模型,挂载verification关联
        $user = new User();
        $user->setRelation('verification', $verification);

        // 构建check模型,挂载user关联
        $check = new Check();
        $check->setRelation('user', $user);

        $mock->shouldReceive('getCheck')->andReturn($check);
    });
});

注意:不要直接通过$user->verification = $verification的方式赋值,该写法会把verification识别为模型表字段而非关联,必须使用setRelation()方法设置关联属性,传入的关联名要和模型中定义的关联方法名完全一致。

方案2:通过模型工厂生成(项目已配置模型工厂时推荐)

如果项目已经为对应模型编写了Laravel模型工厂,可以直接通过工厂级联生成带关联的模型实例,不需要手动调用setRelation(),使用make()方法生成实例不会向数据库写入测试数据:

$app->bind(Service::class, function () {
    return $this->mock(Service::class, function(MockInterface $mock) {
        $mock->makePartial();

        $check = Check::factory()
            ->has(
                User::factory()->has(
                    Verification::factory()->state(['some_id' => 123]),
                    'verification'
                ),
                'user'
            )
            ->make();

        $mock->shouldReceive('getCheck')->andReturn($check);
    });
});
注意事项

使用makePartial()生成的Mock实例只会替换你通过shouldReceive指定的方法,其余类方法会执行原有逻辑,当前场景下仅Mock trait提供的getCheck方法,其余业务逻辑走原生实现,符合单元测试的隔离要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 03:12:33