currentStep = 2; $dto->accommodationId = 1; $dto->dateFrom = new \DateTimeImmutable('2026-03-01'); $dto->dateTo = new \DateTimeImmutable('2026-03-05'); $dto->paxCount = 1; $session = new Session(new MockArraySessionStorage()); $request = Request::create('/groups/booking/step-2', 'POST'); $request->setSession($session); $sessionManager = new AccommodationSessionManager(); $sessionManager->save($request, $dto); $form = $this->createMock(FormInterface::class); $form ->method('handleRequest') ->willReturnCallback(function () use ($dto, $form): FormInterface { $dto->paxCount = 3; return $form; }); $form ->method('isSubmitted') ->willReturn(true); $form ->method('isValid') ->willReturn(true); $accommodation = (new Accommodation()) ->setName('Hotel') ->setCalendarCode('HOTEL') ->setMaxAdolescentAge(17); $bookingService = $this->createMock(AccommodationBookingService::class); $bookingService ->method('loadAccommodation') ->with(1) ->willReturn($accommodation); $bookingService ->method('loadPrices') ->with($dto, $accommodation) ->willReturn([]); $bookingService ->method('loadAvailableServices') ->with($dto, $accommodation) ->willReturn([ 'boardServices' => [], 'additionalServices' => [], 'groupedAdditionalServices' => [], 'ungroupedAdditionalServices' => [], ]); $bookingService ->expects(self::once()) ->method('computeInquiryStatus') ->with(self::callback(static fn (AccommodationBookingDto $submittedDto): bool => 3 === $submittedDto->paxCount), []) ->willReturn(new InquiryStatus(true, ['Mindestaufenthalt: 5 Nächte (gebucht: 4)'])); $controller = new TestableAccommodationStep2Controller( $bookingService, $sessionManager, new GroupsPriceCalculator(new PriceTimelineBuilder(), ['runningCostsEur' => 0, 'runningCostsChf' => 0, 'undersubscription30Eur' => 0, 'undersubscription30Chf' => 0, 'undersubscription40Eur' => 0, 'undersubscription40Chf' => 0]), $form, ); $response = $controller->index($request); self::assertInstanceOf(RedirectResponse::class, $response); self::assertSame('/groups/booking/step-3', $response->headers->get('Location')); self::assertTrue($sessionManager->getOrFail($request)->isInquiry); } } final class TestableAccommodationStep2Controller extends Step2Controller { /** * @param FormInterface $form */ public function __construct( AccommodationBookingService $bookingService, AccommodationSessionManager $sessionManager, GroupsPriceCalculator $priceCalculator, private readonly FormInterface $form, ) { parent::__construct($bookingService, $sessionManager, $priceCalculator); } /** * @return FormInterface */ protected function createForm(string $type, mixed $data = null, array $options = []): FormInterface { return $this->form; } /** * @param array $parameters */ protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse { return new RedirectResponse('/groups/booking/step-3', $status); } /** * @param array $parameters */ protected function render(string $view, array $parameters = [], ?Response $response = null): Response { throw new \LogicException('Render should not be called in this test.'); } }