createUser(['ROLE_CLINIC'])); $this->em->persist($clinic); for ($i = 0; $i < $doctorCount; $i++) { $doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), "دکتر $i"); $slug = 'sp-' . bin2hex(random_bytes(6)); $specialty = new Specialty('تخصص', $slug); $this->em->persist($specialty); $doctor->getSpecialties()->add($specialty); $this->em->persist($doctor); $clinic->getDoctors()->add($doctor); } $this->em->flush(); return $clinic; } public function testQueryCountDoesNotGrowWithDoctorCount(): void { // Keep one kernel/container across both requests so the shared query // logger (doctrine.debug_data_holder) stays consistent. $this->client->disableReboot(); $small = $this->makeClinicWithDoctors(2); $large = $this->makeClinicWithDoctors(6); $qSmall = $this->countQueries(fn () => $this->client->request( 'GET', '/api/v1/clinic/doctor-list/' . $small->getUuid() )); $this->assertSame(200, $this->responseCode()); $qLarge = $this->countQueries(fn () => $this->client->request( 'GET', '/api/v1/clinic/doctor-list/' . $large->getUuid() )); $this->assertSame(200, $this->responseCode()); // No N+1: 4 extra doctors must not add ~4 extra queries. A tiny slack // absorbs one-off warmup variance; the N+1 signal (≈ +doctorCount) is // far larger than the slack. $this->assertLessThanOrEqual($qSmall + 1, $qLarge, "N+1: query count grew from $qSmall to $qLarge with more doctors"); // Correctness preserved: specialties are present in the payload. $body = json_decode($this->client->getResponse()->getContent(), true); $this->assertNotEmpty($body['data']['data'][0]['specialties']); } }