apiClient = new ApiClient( $this->createMock(SerializerInterface::class), $this->createMock(ApiResponseParser::class), $this->createMock(FilesystemOperator::class), $this->createMock(LoggerInterface::class), $this->createMock(BookingDataProcessor::class), new RequestStack(), new RequestIdGenerator(), [ 'bpn_username' => 'test', 'bpn_password' => 'test', 'bpn_api_ip' => '127.0.0.1', 'bpn_api_ports' => [9000], ], ); } public function testEmptyResponseThrowsImmediateConnectionCloseException(): void { $stream = fopen('php://memory', 'r+'); // Write nothing — stream is immediately at EOF rewind($stream); $this->setOperationStartTime(); $this->expectException(ImmediateConnectionCloseException::class); $this->expectExceptionMessage('Server closed connection without sending data'); $this->invokeReceive($stream); } public function testNonEmptyResponseReturnsData(): void { $stream = fopen('php://memory', 'r+'); fwrite($stream, '0000000005Hello'); rewind($stream); $this->setOperationStartTime(); $result = $this->invokeReceive($stream); self::assertSame('0000000005Hello', $result); } private function invokeReceive($socket): string { $method = new \ReflectionMethod(ApiClient::class, 'receive'); return $method->invoke($this->apiClient, $socket); } private function setOperationStartTime(): void { $property = new \ReflectionProperty(ApiClient::class, 'operationStartTime'); $property->setValue($this->apiClient, microtime(true)); } }