getProperty('id'); $idProperty->setValue($ticket, 123); $message = new PostTicketUpdateMessage($ticket, TicketUpdateKindEnum::UPDATE_MOTIVE); // Mock repository to return the Ticket when searching by id $ticketRepository = $this->prophesize(TicketRepositoryInterface::class); $ticketRepository->find(123)->willReturn($ticket)->shouldBeCalledOnce(); // Expect the dispatcher to dispatch a PostTicketUpdateEvent with correct data $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::that(fn ($event) => $event instanceof PostTicketUpdateEvent && TicketUpdateKindEnum::UPDATE_MOTIVE === $event->updateKind && $event->ticket === $ticket)) ->will(fn ($args) => $args[0]) ->shouldBeCalledOnce(); $handler = new PostTicketUpdateMessageHandler($eventDispatcher->reveal(), $ticketRepository->reveal()); // Act $handler($message); // Assert: expectations asserted by Prophecy self::assertTrue(true); } public function testThrowsWhenTicketNotFound(): void { // Arrange: a Ticket with an ID for the message, but repository will return null $ticket = new Ticket(); $reflection = new \ReflectionClass(Ticket::class); $idProperty = $reflection->getProperty('id'); $idProperty->setValue($ticket, 999); $message = new PostTicketUpdateMessage($ticket, TicketUpdateKindEnum::UPDATE_MOTIVE); $ticketRepository = $this->prophesize(TicketRepositoryInterface::class); $ticketRepository->find(999)->willReturn(null)->shouldBeCalledOnce(); $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher->dispatch(Argument::any())->shouldNotBeCalled(); $handler = new PostTicketUpdateMessageHandler($eventDispatcher->reveal(), $ticketRepository->reveal()); // Assert: exception is thrown $this->expectException(UnrecoverableMessageHandlingException::class); $this->expectExceptionMessage('Ticket not found'); // Act $handler($message); } }