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

Laravel测试中使用Factory关联创建Group出现重复记录的解决方法

问题:Laravel工厂使用hasMeetings时生成重复Group记录

Laravel 8.12应用,使用Pest PHP进行测试。groups与meetings表为一对多关系:一个Group拥有多个Meeting,一个Meeting属于一个Group。

单独创建Group时测试正常,Groups表仅存在1条记录;但通过关联关系创建包含Meeting的Group时,Groups表生成了2条记录,不符合预期。

仅创建Group的测试用例

test('user see all meetings and registered groups successful', function () {

   Group::factory()->create();

    dd(Group::pluck('id'));

        actingWithPermission($this->user, $this->permission)
        ->get($this->route)
        ->assertViewHasAll([
            'totalRegistered' => 1,
            'totalMeetings' => 1,
        ]);
});

此时Groups表仅存在1条记录:

^ Illuminate\Support\Collection^ {#3995
  #items: array:1 [
    0 => 36
  ]
  #escapeWhenCastingToString: false
}

关联创建Meeting的Group测试用例

test('user see all meetings and registered groups successful', function () {

   Group::factory()
   ->hasMeetings(1)
   ->create();

    dd(Group::pluck('id'));

        actingWithPermission($this->user, $this->permission)
        ->get($this->route)
        ->assertViewHasAll([
            'totalRegistered' => 1,
            'totalMeetings' => 1,
        ]);
});

此时Groups表存在2条记录:

^ Illuminate\Support\Collection^ {#1847
  #items: array:2 [
    0 => 36
    1 => 37
  ]
  #escapeWhenCastingToString: false
}

Group模型中的关系定义

public function meetings()
{
    return $this->hasMany(Meeting::class);
}

修复方案

问题根源在于Meeting工厂的定义中自动创建了关联的Group,导致调用hasMeetings(1)时出现重复创建:

  1. 首先Group::factory()->hasMeetings(1)->create()会创建一个Group;
  2. 随后Meeting工厂在生成Meeting时,又自动创建了另一个Group来关联,最终产生两条Group记录。

具体修复步骤:

  1. 检查Meeting工厂的代码,若存在类似以下自动创建Group的逻辑,需要移除或调整:
// 错误示例:Meeting工厂自动创建Group
class MeetingFactory extends Factory
{
    public function definition()
    {
        return [
            'group_id' => Group::factory(), // 这里会自动创建新Group
            // 其他字段
        ];
    }
}
  1. 修改Meeting工厂,让它依赖外部传入的group_id,而非自动创建:
class MeetingFactory extends Factory
{
    public function definition()
    {
        return [
            // 只定义其他字段,不自动生成group_id
            'title' => $this->faker->sentence(),
            // ...其他字段
        ];
    }

    // 可选:添加一个状态方法,用于关联指定Group
    public function forGroup(Group $group)
    {
        return $this->state(fn (array $attributes) => [
            'group_id' => $group->id,
        ]);
    }
}

修改后,Group::factory()->hasMeetings(1)->create()会自动将生成的Meeting关联到当前创建的Group,不会额外创建新的Group,Groups表只会有1条记录。

或者,也可以在调用hasMeetings时显式指定关联的Group,避免重复创建:

Group::factory()
    ->hasMeetings(1, function (array $attributes, Group $group) {
        return ['group_id' => $group->id];
    })
    ->create();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:45:21