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

Laravel批量创建StudentSection的PHPUnit测试断言失败排查

Laravel批量创建学生班级测试断言失败问题排查

我是Laravel新手,刚接触PHPUnit,测试批量创建学生班级(StudentSection)的setStudentsSection方法时,写了testCanMassAssignSection测试用例,结果断言失败。预期student.sections表中存在指定student_id和section_id的行,但实际只创建了一条其他student_id的记录,找不到问题所在。


业务代码

public function setStudentsSection(Request $request)
{
    $enrollments = Enrollment::whereIn('student_id', $request->students)->where('session_id', $request->session_id)->get();
    $program_section = ProgramSection::withCount('students')->find($request->program_section_id);
    if(($program_section->students_count + count($enrollments)) <= $program_section->max_students) {
        foreach($enrollments as $enrollment) {
            $response = StudentSection::create([
                'student_id'    => $enrollment->student_id,
                'enrollment_id' => $enrollment->id,
                'section_id'    => $request->program_section_id,
                'created_at'    => Carbon::now()
            ]);
            return $response;
        }
    }
    return response()->json(['errors' => ['message' => 'Selected Section is full.']], 405);
}

测试代码

测试用例

public function testCanMassAssignSection()
{
    $sectioning_data = $this->setMassSectioning(10);
    
    $this->json('POST', 'api/enrollments/set-students-section', $sectioning_data['data'])
        ->assertStatus(201);
    $student_section_data = ['student_id' => $sectioning_data['student_ids'], 'section_id' => $sectioning_data['program_section']->id];
    $this->assertDatabaseHas('student.sections', $student_section_data);
}

测试辅助方法

private function setMassSectioning($max_students)
{
    $session = Session::factory()->create();
    $program_section = ProgramSection::factory()->create(['session_id' => $session->id, 'max_students' => $max_students]);
    $enrollments = Enrollment::factory(['session_id' => $session->id])->count(3)->create();
    $student_ids = array();
    foreach($enrollments as $enrollment) {
        array_push($student_ids, $enrollment->student_id);
    }

    return  [
        'data'              => ['program_section_id' => $program_section->id, 'session_id' => $session->id, 'students' => $student_ids],
        'student_ids'       => $enrollment->student_id,
        'program_section'   => $program_section
    ];
}

错误信息

1) Test\Feature\EnrollmentTest::testCanMassAssignSection
Failed asserting that a row in the table [student.sections] matches the attributes {
    "student_id": 2765,
    "section_id": 1649
}.

Found: [
    {
        "id": 262,
        "student_id": 2763,
        "section_id": 1649,
        "created_at": "2022-08-24 09:32:05",
        "updated_at": "2022-08-24 09:32:05",
        "enrollment_id": 1740
    }
].

问题修复方案

1. 业务方法循环提前返回导致只创建一条记录

业务代码的foreach循环内,创建完第一条记录就直接return $response,导致循环终止,只生成第一条学生的班级记录。修改如下:

public function setStudentsSection(Request $request)
{
    $enrollments = Enrollment::whereIn('student_id', $request->students)->where('session_id', $request->session_id)->get();
    $program_section = ProgramSection::withCount('students')->find($request->program_section_id);
    
    if(($program_section->students_count + $enrollments->count()) <= $program_section->max_students) {
        $createdRecords = [];
        foreach($enrollments as $enrollment) {
            $createdRecords[] = StudentSection::create([
                'student_id'    => $enrollment->student_id,
                'enrollment_id' => $enrollment->id,
                'section_id'    => $request->program_section_id,
                'created_at'    => Carbon::now()
            ]);
        }
        // 循环结束后统一返回所有创建的记录
        return response()->json($createdRecords, 201);
    }
    
    return response()->json(['errors' => ['message' => 'Selected Section is full.']], 405);
}

2. 测试辅助方法返回错误的学生ID

setMassSectioning方法中,返回的student_ids是循环最后一个$enrollment的ID,而非收集到的所有学生ID数组。修改如下:

return  [
    'data'              => ['program_section_id' => $program_section->id, 'session_id' => $session->id, 'students' => $student_ids],
    'student_ids'       => $student_ids, // 改为返回收集的所有学生ID数组
    'program_section'   => $program_section
];

3. 测试断言需遍历所有学生ID验证

原测试仅验证单个学生ID,需改为遍历所有生成的学生ID,逐一验证记录是否存在:

public function testCanMassAssignSection()
{
    $sectioning_data = $this->setMassSectioning(10);
    
    $this->json('POST', 'api/enrollments/set-students-section', $sectioning_data['data'])
        ->assertStatus(201);
    
    // 遍历所有学生ID,逐一验证对应记录是否存在
    foreach($sectioning_data['student_ids'] as $student_id) {
        $this->assertDatabaseHas('student.sections', [
            'student_id' => $student_id, 
            'section_id' => $sectioning_data['program_section']->id
        ]);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:42:39