From 55fa0fac6b75741415c3b99c38efec21f022db09 Mon Sep 17 00:00:00 2001 From: "rob.leney" Date: Tue, 7 Jul 2026 13:40:23 +1000 Subject: [PATCH] RAID-731: Skip DataCite error test when mockserver unavailable The test previously created a mockserver expectation dynamically at runtime, which failed with connection refused in the Branch-Build-Deploy pipeline where no Docker stack runs. The DataCite 429 expectation is now defined statically in expectations.json (matched by a sentinel string in the raid title, priority 10 over the generic 201 expectations), and the test skips via JUnit Assumptions when mockserver at localhost:1080 is unreachable. Co-Authored-By: Claude Fable 5 --- .../mockserver/expectations.json | 21 +++++ .../inttest/DataciteErrorIntegrationTest.java | 93 +++++-------------- 2 files changed, 44 insertions(+), 70 deletions(-) diff --git a/api-svc/raid-api/docker-compose/mockserver/expectations.json b/api-svc/raid-api/docker-compose/mockserver/expectations.json index ac8ba79c9..b780cc394 100644 --- a/api-svc/raid-api/docker-compose/mockserver/expectations.json +++ b/api-svc/raid-api/docker-compose/mockserver/expectations.json @@ -404,6 +404,27 @@ } } }, + { + "priority": 10, + "httpRequest": { + "method": "POST", + "path": "/dois", + "body": { + "type": "STRING", + "string": "RAID-731-DATACITE-ERROR", + "subString": true + } + }, + "httpResponse": { + "statusCode": 429, + "headers": { + "Content-Type": ["application/json"] + }, + "body": { + "errors": [{"status": "429", "title": "Too Many Requests"}] + } + } + }, { "httpRequest": { "method": "POST", diff --git a/api-svc/raid-api/src/intTest/java/au/org/raid/inttest/DataciteErrorIntegrationTest.java b/api-svc/raid-api/src/intTest/java/au/org/raid/inttest/DataciteErrorIntegrationTest.java index 14b8fdc32..e5ef5fe0f 100644 --- a/api-svc/raid-api/src/intTest/java/au/org/raid/inttest/DataciteErrorIntegrationTest.java +++ b/api-svc/raid-api/src/intTest/java/au/org/raid/inttest/DataciteErrorIntegrationTest.java @@ -1,59 +1,46 @@ package au.org.raid.inttest; import feign.FeignException; -import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; public class DataciteErrorIntegrationTest extends AbstractIntegrationTest { - private static final String MOCKSERVER_EXPECTATION_URL = "http://localhost:1080/mockserver/expectation"; - private static final String EXPECTATION_ID = "datacite-error-integration-test"; - - @Autowired - private RestTemplate restTemplate; + private static final String MOCKSERVER_HOST = "localhost"; + private static final int MOCKSERVER_PORT = 1080; + private static final int MOCKSERVER_CONNECT_TIMEOUT_MILLIS = 2000; - @AfterEach - void cleanUpMockServerExpectation() { - final var cleanup = """ - [{ - "id": "%s", - "priority": 0, - "httpRequest": { - "method": "POST", - "path": "/dois" - }, - "httpResponse": { - "statusCode": 201 - }, - "times": { - "remainingTimes": 0, - "unlimited": false - } - }] - """.formatted(EXPECTATION_ID); + // Sentinel matched by the static 429 expectation in docker-compose/mockserver/expectations.json + private static final String DATACITE_ERROR_TITLE_SENTINEL = "RAID-731-DATACITE-ERROR"; - var headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); + @BeforeEach + void checkMockServerIsReachable() { + Assumptions.assumeTrue(isMockServerReachable(), "mockserver not reachable - skipping DataCite error test"); + } - try { - restTemplate.put(MOCKSERVER_EXPECTATION_URL, new HttpEntity<>(cleanup, headers)); - } catch (Exception ignored) { + private static boolean isMockServerReachable() { + try (var socket = new Socket()) { + socket.connect(new InetSocketAddress(MOCKSERVER_HOST, MOCKSERVER_PORT), MOCKSERVER_CONNECT_TIMEOUT_MILLIS); + return true; + } catch (IOException e) { + return false; } } @Test @DisplayName("Mint fails when DataCite returns an error") void mintFailsOnDataciteError() { - createDataciteErrorExpectation(); + createRequest.getTitle().get(0).setText(DATACITE_ERROR_TITLE_SENTINEL + " " + UUID.randomUUID()); try { raidApi.mintRaid(createRequest); @@ -62,38 +49,4 @@ void mintFailsOnDataciteError() { assertThat(e.status()).isEqualTo(500); } } - - private void createDataciteErrorExpectation() { - final var expectation = """ - [{ - "id": "%s", - "priority": 10, - "httpRequest": { - "method": "POST", - "path": "/dois", - "headers": { - "Authorization": ["Basic ZGF0YWNpdGUtdXNlcm5hbWU6ZGF0YWNpdGUtcGFzc3dvcmQ="], - "Content-Type": ["application/json"] - } - }, - "httpResponse": { - "statusCode": 429, - "headers": { - "Content-Type": ["application/json"] - }, - "body": { - "errors": [{"status": "429", "title": "Too Many Requests"}] - } - }, - "times": { - "remainingTimes": 1, - "unlimited": false - } - }] - """.formatted(EXPECTATION_ID); - - var headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - restTemplate.put(MOCKSERVER_EXPECTATION_URL, new HttpEntity<>(expectation, headers)); - } }