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
相关产品推荐
相关产品推荐

