repository = new InMemoryStudentGuardianRepository(); $clock = new class implements Clock { public function now(): DateTimeImmutable { return new DateTimeImmutable('2026-02-10 10:00:00'); } }; $this->handler = new UnlinkParentFromStudentHandler($this->repository, $clock); } #[Test] public function unlinkRemovesExistingLink(): void { $link = $this->createAndSaveLink(); ($this->handler)(new UnlinkParentFromStudentCommand( linkId: (string) $link->id, tenantId: self::TENANT_ID, )); self::assertSame(0, $this->repository->countGuardiansForStudent( $link->studentId, $link->tenantId, )); } #[Test] public function unlinkRecordsParentDelieDEleveEvent(): void { $link = $this->createAndSaveLink(); $result = ($this->handler)(new UnlinkParentFromStudentCommand( linkId: (string) $link->id, tenantId: self::TENANT_ID, )); $events = $result->pullDomainEvents(); self::assertCount(1, $events); self::assertInstanceOf(ParentDelieDEleve::class, $events[0]); self::assertTrue($events[0]->studentId->equals($link->studentId)); self::assertTrue($events[0]->guardianId->equals($link->guardianId)); } #[Test] public function throwsWhenLinkNotFound(): void { $this->expectException(StudentGuardianNotFoundException::class); ($this->handler)(new UnlinkParentFromStudentCommand( linkId: '550e8400-e29b-41d4-a716-446655440099', tenantId: self::TENANT_ID, )); } private function createAndSaveLink(): StudentGuardian { $link = StudentGuardian::lier( studentId: UserId::fromString(self::STUDENT_ID), guardianId: UserId::fromString(self::GUARDIAN_ID), relationshipType: RelationshipType::FATHER, tenantId: TenantId::fromString(self::TENANT_ID), createdAt: new DateTimeImmutable('2026-02-10 10:00:00'), ); // Drain lier() events so only delier() events are tested $link->pullDomainEvents(); $this->repository->save($link); return $link; } }