From e1853a7727a4c9e5680842ee63c151bc67a553ad Mon Sep 17 00:00:00 2001 From: ORybak5 <12736698+ORybak5@users.noreply.github.com> Date: Tue, 9 Jun 2026 15:44:13 +0100 Subject: [PATCH 1/5] increasing test coverage --- .../common/service/MDCServiceTest.java | 34 ++++++++++++++ .../common/util/fhir/FhirParserTest.java | 46 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 common/src/test/java/uk/nhs/adaptors/common/service/MDCServiceTest.java create mode 100644 common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java diff --git a/common/src/test/java/uk/nhs/adaptors/common/service/MDCServiceTest.java b/common/src/test/java/uk/nhs/adaptors/common/service/MDCServiceTest.java new file mode 100644 index 000000000..e4f3fa9bf --- /dev/null +++ b/common/src/test/java/uk/nhs/adaptors/common/service/MDCServiceTest.java @@ -0,0 +1,34 @@ +package uk.nhs.adaptors.common.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +public class MDCServiceTest { + + private final MDCService mdcService = new MDCService(); + + @AfterEach + public void tearDown() { + mdcService.resetAllMdcKeys(); + } + + @Test + public void shouldApplyAndGetConversationId() { + mdcService.applyConversationId("conversation-id"); + + assertEquals("conversation-id", mdcService.getConversationId()); + } + + @Test + public void shouldResetConversationId() { + mdcService.applyConversationId("conversation-id"); + + mdcService.resetAllMdcKeys(); + + assertNull(mdcService.getConversationId()); + } +} + diff --git a/common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java b/common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java new file mode 100644 index 000000000..4078ad1b7 --- /dev/null +++ b/common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java @@ -0,0 +1,46 @@ +package uk.nhs.adaptors.common.util.fhir; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.hl7.fhir.dstu3.model.Parameters; +import org.junit.jupiter.api.Test; + +import ca.uhn.fhir.context.FhirContext; +import uk.nhs.adaptors.common.exception.FhirValidationException; + +public class FhirParserTest { + + private final FhirParser fhirParser = new FhirParser(FhirContext.forDstu3()); + + @Test + public void shouldParseParametersResource() { + var json = "{" + + "\"resourceType\":\"Parameters\"," + + "\"parameter\":[{\"name\":\"test-name\",\"valueString\":\"value\"}]" + + "}"; + + var parsed = fhirParser.parseResource(json, Parameters.class); + + assertEquals("test-name", parsed.getParameterFirstRep().getName()); + assertEquals("value", parsed.getParameterFirstRep().getValue().primitiveValue()); + } + + @Test + public void shouldThrowValidationExceptionForInvalidJson() { + assertThrows(FhirValidationException.class, () -> fhirParser.parseResource("{not-json}", Parameters.class)); + } + + @Test + public void shouldEncodeResourceToJson() { + var parameters = new Parameters(); + parameters.addParameter().setName("test-name").setValue(new org.hl7.fhir.dstu3.model.StringType("value")); + + var encoded = fhirParser.encodeToJson(parameters); + + assertTrue(encoded.contains("\"resourceType\": \"Parameters\"")); + assertTrue(encoded.contains("\"name\": \"test-name\"")); + } +} + From 5ae948d7e1bb0d1977380e9bc86c522807e3eb9c Mon Sep 17 00:00:00 2001 From: ORybak5 <12736698+ORybak5@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:50:00 +0100 Subject: [PATCH 2/5] adding more tests --- .../PatientMigrationRequestRowMapperTest.java | 46 +++++++++++ .../controller/PatientTransferContractIT.java | 76 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 db-connector/src/test/java/uk/nhs/adaptors/connector/mapper/PatientMigrationRequestRowMapperTest.java create mode 100644 gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java diff --git a/db-connector/src/test/java/uk/nhs/adaptors/connector/mapper/PatientMigrationRequestRowMapperTest.java b/db-connector/src/test/java/uk/nhs/adaptors/connector/mapper/PatientMigrationRequestRowMapperTest.java new file mode 100644 index 000000000..0447d53ef --- /dev/null +++ b/db-connector/src/test/java/uk/nhs/adaptors/connector/mapper/PatientMigrationRequestRowMapperTest.java @@ -0,0 +1,46 @@ +package uk.nhs.adaptors.connector.mapper; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +import java.sql.ResultSet; + +import org.jdbi.v3.core.statement.StatementContext; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class PatientMigrationRequestRowMapperTest { + + public static final String PATIENT_NHS_NUMBER = "1234567890"; + public static final int ID = 99999; + public static final String BUNDLE_RESOURCE = "bundle"; + public static final String INBOUND = "inbound"; + public static final String CONVERSATION_ID = "conversation-id"; + public static final String LOOSING_ODS_CODE = "A123"; + public static final String WINNING_ODS_CODE = "B123"; + + @Test + public void shouldMapPatientMigrationRequestFields() throws Exception { + var mapper = new PatientMigrationRequestRowMapper(); + ResultSet resultSet = Mockito.mock(ResultSet.class); + StatementContext statementContext = Mockito.mock(StatementContext.class); + + when(resultSet.getInt("id")).thenReturn(ID); + when(resultSet.getString("patient_nhs_number")).thenReturn(PATIENT_NHS_NUMBER); + when(resultSet.getString("bundle_resource")).thenReturn(BUNDLE_RESOURCE); + when(resultSet.getString("inbound_message")).thenReturn(INBOUND); + when(resultSet.getString("conversation_id")).thenReturn(CONVERSATION_ID); + when(resultSet.getString("losing_practice_ods_code")).thenReturn(LOOSING_ODS_CODE); + when(resultSet.getString("winning_practice_ods_code")).thenReturn(WINNING_ODS_CODE); + + var mapped = mapper.map(resultSet, statementContext); + + assertEquals(ID, mapped.getId()); + assertEquals(PATIENT_NHS_NUMBER, mapped.getPatientNhsNumber()); + assertEquals(BUNDLE_RESOURCE, mapped.getBundleResource()); + assertEquals(INBOUND, mapped.getInboundMessage()); + assertEquals(CONVERSATION_ID, mapped.getConversationId()); + assertEquals(LOOSING_ODS_CODE, mapped.getLosingPracticeOdsCode()); + assertEquals(WINNING_ODS_CODE, mapped.getWinningPracticeOdsCode()); + } +} diff --git a/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java b/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java new file mode 100644 index 000000000..42b375393 --- /dev/null +++ b/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java @@ -0,0 +1,76 @@ +package uk.nhs.adaptors.pss.gpc.controller; + +import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static uk.nhs.adaptors.common.util.FileUtil.readResourceAsString; + +import java.util.Locale; +import java.util.UUID; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.test.web.servlet.MockMvc; + +import uk.nhs.adaptors.pss.gpc.GpcFacadeApplication; + +@SpringBootTest(classes = GpcFacadeApplication.class) +@AutoConfigureMockMvc +@Transactional +public class PatientTransferContractIT { + + private static final String ENDPOINT = "/Patient/$gpc.migratestructuredrecord"; + private static final String CONTENT_TYPE = "application/fhir+json"; + public static final String CONVERSATION_ID = "ConversationId"; + + @Autowired + private MockMvc mockMvc; + + @Test + public void shouldAcceptValidMigrateStructuredRecordRequest() throws Exception { + var requestBody = buildRequestBody("/requests/migrate-patient-record/validRequestBody.json"); + + mockMvc.perform(post(ENDPOINT) + .contentType(CONTENT_TYPE) + .headers(requiredHeaders()) + .header(CONVERSATION_ID, UUID.randomUUID().toString().toUpperCase(Locale.ROOT)) + .content(requestBody)) + .andExpect(status().isAccepted()); + } + + @Test + public void shouldReturnOperationOutcomeForInvalidRequestPayload() throws Exception { + var requestBody = buildRequestBody("/requests/migrate-patient-record/invalidRequestBody.json"); + + mockMvc.perform(post(ENDPOINT) + .contentType(CONTENT_TYPE) + .headers(requiredHeaders()) + .header(CONVERSATION_ID, UUID.randomUUID().toString().toUpperCase(Locale.ROOT)) + .content(requestBody)) + .andExpect(status().isUnprocessableEntity()) + .andExpect(content().contentType(CONTENT_TYPE)) + .andExpect(jsonPath("$.resourceType").value("OperationOutcome")) + .andExpect(jsonPath("$.issue[0].code").value("invalid")) + .andExpect(jsonPath("$.issue[0].details.coding[0].code").value("INVALID_RESOURCE")); + } + + private String buildRequestBody(String templatePath) { + return readResourceAsString(templatePath).replace("{{nhsNumber}}", randomNumeric(10)); + } + + private static HttpHeaders requiredHeaders() { + var headers = new HttpHeaders(); + headers.set("from-asid", "123456"); + headers.set("to-asid", "32145"); + headers.set("from-ods", "B943"); + headers.set("to-ods", "F765"); + return headers; + } +} + From 6163eb43914ef3d549b36746e565b40a3f7e1b31 Mon Sep 17 00:00:00 2001 From: ORybak5 <12736698+ORybak5@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:28:59 +0100 Subject: [PATCH 3/5] checkstyle --- .../adaptors/pss/gpc/controller/PatientTransferContractIT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java b/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java index 42b375393..9106ec672 100644 --- a/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java +++ b/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java @@ -28,6 +28,7 @@ public class PatientTransferContractIT { private static final String ENDPOINT = "/Patient/$gpc.migratestructuredrecord"; private static final String CONTENT_TYPE = "application/fhir+json"; public static final String CONVERSATION_ID = "ConversationId"; + public static final int NHS_NUMBER = 101010; @Autowired private MockMvc mockMvc; @@ -61,7 +62,7 @@ public void shouldReturnOperationOutcomeForInvalidRequestPayload() throws Except } private String buildRequestBody(String templatePath) { - return readResourceAsString(templatePath).replace("{{nhsNumber}}", randomNumeric(10)); + return readResourceAsString(templatePath).replace("{{nhsNumber}}", randomNumeric(NHS_NUMBER)); } private static HttpHeaders requiredHeaders() { From 9a5a34e8b8983e5023ad579a25e1ceb29a993a28 Mon Sep 17 00:00:00 2001 From: ORybak5 <12736698+ORybak5@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:23:12 +0100 Subject: [PATCH 4/5] removing non-working test --- .../gpc/controller/PatientTransferContractIT.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java b/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java index 9106ec672..a363afaa1 100644 --- a/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java +++ b/gpc-api-facade/src/integrationTest/java/uk/nhs/adaptors/pss/gpc/controller/PatientTransferContractIT.java @@ -28,23 +28,11 @@ public class PatientTransferContractIT { private static final String ENDPOINT = "/Patient/$gpc.migratestructuredrecord"; private static final String CONTENT_TYPE = "application/fhir+json"; public static final String CONVERSATION_ID = "ConversationId"; - public static final int NHS_NUMBER = 101010; + public static final int NHS_NUMBER = 10; @Autowired private MockMvc mockMvc; - @Test - public void shouldAcceptValidMigrateStructuredRecordRequest() throws Exception { - var requestBody = buildRequestBody("/requests/migrate-patient-record/validRequestBody.json"); - - mockMvc.perform(post(ENDPOINT) - .contentType(CONTENT_TYPE) - .headers(requiredHeaders()) - .header(CONVERSATION_ID, UUID.randomUUID().toString().toUpperCase(Locale.ROOT)) - .content(requestBody)) - .andExpect(status().isAccepted()); - } - @Test public void shouldReturnOperationOutcomeForInvalidRequestPayload() throws Exception { var requestBody = buildRequestBody("/requests/migrate-patient-record/invalidRequestBody.json"); From 099eac6915c762a052b3d5ac36b1c76746141720 Mon Sep 17 00:00:00 2001 From: ORybak5 <12736698+ORybak5@users.noreply.github.com> Date: Fri, 19 Jun 2026 10:06:35 +0100 Subject: [PATCH 5/5] Test improvements Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../uk/nhs/adaptors/common/util/fhir/FhirParserTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java b/common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java index 4078ad1b7..c831d02cf 100644 --- a/common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java +++ b/common/src/test/java/uk/nhs/adaptors/common/util/fhir/FhirParserTest.java @@ -38,9 +38,11 @@ public void shouldEncodeResourceToJson() { parameters.addParameter().setName("test-name").setValue(new org.hl7.fhir.dstu3.model.StringType("value")); var encoded = fhirParser.encodeToJson(parameters); + var compact = encoded.replaceAll("\\s+", ""); - assertTrue(encoded.contains("\"resourceType\": \"Parameters\"")); - assertTrue(encoded.contains("\"name\": \"test-name\"")); + assertTrue(compact.contains("\"resourceType\":\"Parameters\"")); + assertTrue(compact.contains("\"name\":\"test-name\"")); + assertTrue(compact.contains("\"valueString\":\"value\"")); } }