textAnnotation) {
+ CdsElement el = mock(CdsElement.class);
+ when(el.getName()).thenReturn(name);
+ CdsType type = mock(CdsType.class);
+ lenient().when(type.getQualifiedName()).thenReturn(cdsType);
+ lenient().when(el.getType()).thenReturn(type);
+ when(el.findAnnotation("@Common.ValueList")).thenReturn(Optional.empty());
+ Optional valueListAnn =
+ hasValueList ? Optional.of(mock(CdsAnnotation.class)) : Optional.empty();
+ when(el.findAnnotation("@Common.ValueListWithFixedValues")).thenReturn(valueListAnn);
+ lenient().when(el.findAnnotation("@Common.Text")).thenReturn((Optional) textAnnotation);
+ return el;
+ }
+}
diff --git a/srv/src/test/java/com/sap/cds/feature/ai/client/AICoreClientPredictionTest.java b/srv/src/test/java/com/sap/cds/feature/ai/client/AICoreClientPredictionTest.java
new file mode 100644
index 0000000..bdf43a0
--- /dev/null
+++ b/srv/src/test/java/com/sap/cds/feature/ai/client/AICoreClientPredictionTest.java
@@ -0,0 +1,232 @@
+/*
+ * © 2026 SAP SE or an SAP affiliate company and cds-feature-ai contributors.
+ */
+package com.sap.cds.feature.ai.client;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sap.cds.feature.ai.client.setup.AICoreSetupHandler;
+import com.sap.cds.services.environment.CdsEnvironment;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.mockito.Mockito;
+
+/**
+ * Integration test verifying the full prediction flow against a real AI Core instance.
+ *
+ * Required environment variables: AICORE_SERVICE_KEY – Full AI Core service key JSON: {
+ * "clientid": "...", "clientsecret": "...", "url": "...", "serviceurls": { "AI_API_URL": "..." } }
+ */
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+class AICoreClientPredictionTest {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private AICoreClient cut;
+ private Map credentials;
+ private String resourceGroup;
+
+ @BeforeAll
+ void setup() throws Exception {
+ String serviceKey = System.getenv("AICORE_SERVICE_KEY");
+ assumeTrue(serviceKey != null, "Skipping integration test: AICORE_SERVICE_KEY env var not set");
+
+ credentials = MAPPER.readValue(serviceKey, new TypeReference<>() {});
+ resourceGroup = "default";
+ CdsEnvironment environment = Mockito.mock(CdsEnvironment.class);
+ cut = new AICoreClient(new AICoreSetupHandler(environment));
+ }
+
+ /**
+ * Full prediction flow: 1. Check deployments in the resource group 2. If no RUNNING rpt-1
+ * deployment exists, create one and wait for it to reach RUNNING 3. Call fetchPredictions with a
+ * small context row and a [PREDICT] row 4. Verify predictions are returned
+ */
+ @Test
+ void prediction_deploymentMissingOrPresent_returnsPredictions() throws Exception {
+ String aiApiUrl = ((Map, ?>) credentials.get("serviceurls")).get("AI_API_URL").toString();
+ String token = fetchToken();
+
+ // Step 1+2: ensure a RUNNING rpt-1 deployment exists (create if missing)
+ ensureRunningRpt1Deployment(aiApiUrl, token);
+
+ // Step 3: build rows — two context rows + one [PREDICT] row
+ Map contextRow1 = new HashMap<>();
+ contextRow1.put("ID", "ctx-1");
+ contextRow1.put("genre_ID", 10);
+ contextRow1.put("title", "Eleonora");
+
+ Map contextRow2 = new HashMap<>();
+ contextRow2.put("ID", "ctx-2");
+ contextRow2.put("genre_ID", 20);
+ contextRow2.put("title", "Another Book");
+
+ Map predictRow = new HashMap<>();
+ predictRow.put("ID", "predict-1");
+ predictRow.put("genre_ID", "[PREDICT]");
+ predictRow.put("title", "Eleonora");
+
+ List