|
7 | 7 | import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; |
8 | 8 | import static com.github.tomakehurst.wiremock.client.WireMock.get; |
9 | 9 | import static com.github.tomakehurst.wiremock.client.WireMock.jsonResponse; |
| 10 | +import static com.github.tomakehurst.wiremock.client.WireMock.noContent; |
10 | 11 | import static com.github.tomakehurst.wiremock.client.WireMock.okJson; |
| 12 | +import static com.github.tomakehurst.wiremock.client.WireMock.okXml; |
11 | 13 | import static com.github.tomakehurst.wiremock.client.WireMock.post; |
12 | 14 | import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; |
13 | 15 | import static com.github.tomakehurst.wiremock.client.WireMock.serverError; |
|
21 | 23 | import static org.assertj.core.api.Assertions.assertThatThrownBy; |
22 | 24 | import static org.mockito.Mockito.mock; |
23 | 25 |
|
| 26 | +import com.fasterxml.jackson.core.JsonParseException; |
24 | 27 | import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; |
25 | 28 | import com.github.tomakehurst.wiremock.junit5.WireMockTest; |
| 29 | +import com.github.tomakehurst.wiremock.stubbing.Scenario; |
26 | 30 | import com.sap.ai.sdk.core.AiCoreService; |
27 | 31 | import com.sap.ai.sdk.orchestration.client.model.AzureContentSafety; |
28 | 32 | import com.sap.ai.sdk.orchestration.client.model.AzureThreshold; |
|
47 | 51 | import java.util.Objects; |
48 | 52 | import java.util.function.Function; |
49 | 53 | import javax.annotation.Nonnull; |
| 54 | +import org.assertj.core.api.SoftAssertions; |
50 | 55 | import org.junit.jupiter.api.BeforeEach; |
51 | 56 | import org.junit.jupiter.api.Test; |
52 | 57 |
|
@@ -339,26 +344,74 @@ private static MaskingModuleConfig createMaskingConfig( |
339 | 344 | } |
340 | 345 |
|
341 | 346 | @Test |
342 | | - void testGenericErrorHandling() { |
343 | | - stubFor(post(anyUrl()).willReturn(serverError())); |
344 | | - |
345 | | - assertThatThrownBy(() -> client.executeRequest(mock(CompletionPostRequest.class))) |
346 | | - .isInstanceOf(OrchestrationClientException.class) |
347 | | - .hasMessageContaining("500 Server Error"); |
348 | | - } |
349 | | - |
350 | | - @Test |
351 | | - void testOrchestrationErrorParsing() { |
| 347 | + void testErrorHandling() { |
352 | 348 | stubFor( |
353 | 349 | post(anyUrl()) |
| 350 | + .inScenario("Errors") |
| 351 | + .whenScenarioStateIs(Scenario.STARTED) |
| 352 | + .willReturn(serverError()) |
| 353 | + .willSetStateTo("1")); |
| 354 | + stubFor( |
| 355 | + post(anyUrl()) |
| 356 | + .inScenario("Errors") |
| 357 | + .whenScenarioStateIs("1") |
354 | 358 | .willReturn( |
355 | 359 | badRequest() |
356 | 360 | .withHeader("Content-Type", "application/json") |
357 | | - .withBodyFile("errorResponse.json"))); |
| 361 | + .withBodyFile("errorResponse.json")) |
| 362 | + .willSetStateTo("2")); |
| 363 | + stubFor( |
| 364 | + post(anyUrl()) |
| 365 | + .inScenario("Errors") |
| 366 | + .whenScenarioStateIs("2") |
| 367 | + .willReturn( |
| 368 | + badRequest() |
| 369 | + .withBody("{ broken json") |
| 370 | + .withHeader("Content-type", "application/json")) |
| 371 | + .willSetStateTo("3")); |
| 372 | + stubFor( |
| 373 | + post(anyUrl()) |
| 374 | + .inScenario("Errors") |
| 375 | + .whenScenarioStateIs("3") |
| 376 | + .willReturn(okXml("<xml></xml>")) |
| 377 | + .willSetStateTo("4")); |
| 378 | + stubFor(post(anyUrl()).inScenario("Errors").whenScenarioStateIs("4").willReturn(noContent())); |
| 379 | + |
| 380 | + final var softly = new SoftAssertions(); |
| 381 | + final Runnable request = () -> client.executeRequest(mock(CompletionPostRequest.class)); |
| 382 | + |
| 383 | + softly |
| 384 | + .assertThatThrownBy(request::run) |
| 385 | + .describedAs("Server errors should be handled") |
| 386 | + .isInstanceOf(OrchestrationClientException.class) |
| 387 | + .hasMessageContaining("500"); |
358 | 388 |
|
359 | | - assertThatThrownBy(() -> client.executeRequest(mock(CompletionPostRequest.class))) |
| 389 | + softly |
| 390 | + .assertThatThrownBy(request::run) |
| 391 | + .describedAs("Error objects from Orchestration should be interpreted") |
360 | 392 | .isInstanceOf(OrchestrationClientException.class) |
361 | | - .hasMessageContaining("400 Bad Request") |
362 | 393 | .hasMessageContaining("'orchestration_config' is a required property"); |
| 394 | + |
| 395 | + softly |
| 396 | + .assertThatThrownBy(request::run) |
| 397 | + .describedAs("Failures while parsing error message should be handled") |
| 398 | + .isInstanceOf(OrchestrationClientException.class) |
| 399 | + .hasMessageContaining("400") |
| 400 | + .extracting(e -> e.getSuppressed()[0]) |
| 401 | + .isInstanceOf(JsonParseException.class); |
| 402 | + |
| 403 | + softly |
| 404 | + .assertThatThrownBy(request::run) |
| 405 | + .describedAs("Non-JSON responses should be handled") |
| 406 | + .isInstanceOf(OrchestrationClientException.class) |
| 407 | + .hasMessageContaining("Failed to parse"); |
| 408 | + |
| 409 | + softly |
| 410 | + .assertThatThrownBy(request::run) |
| 411 | + .describedAs("Empty responses should be handled") |
| 412 | + .isInstanceOf(OrchestrationClientException.class) |
| 413 | + .hasMessageContaining("was empty"); |
| 414 | + |
| 415 | + softly.assertAll(); |
363 | 416 | } |
364 | 417 | } |
0 commit comments