From 11a11da7c3f618d8117e3b92c3386bdd1465920a Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 1 Nov 2024 12:40:48 -0400 Subject: [PATCH] Add FHIRToolingClient tests --- .../dstu2/utils/client/FHIRToolingClient.java | 15 +- .../dstu2/utils/client/ResourceAddress.java | 5 +- .../dstu2/utils/client/ClientUtilsTest.java | 50 ++++-- .../utils/client/FHIRToolingClientTest.java | 167 ++++++++++++++++++ .../utils/client/FhirToolingClientTest.java | 1 - 5 files changed, 215 insertions(+), 23 deletions(-) create mode 100644 org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClientTest.java diff --git a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java index c62f1cb75..f21856d94 100644 --- a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java @@ -95,12 +95,17 @@ public class FHIRToolingClient extends FHIRBaseToolingClient { private HttpHost proxy; private int maxResultSetSize = -1;// _count private Conformance conf; - private ClientUtils utils = new ClientUtils(); + private ClientUtils utils = null; private int useCount; + protected ClientUtils getClientUtils() { + return new ClientUtils(); + } + // Pass enpoint for client - URI public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException { preferredResourceFormat = ResourceFormat.RESOURCE_XML; + utils = getClientUtils(); utils.setUserAgent(userAgent); detectProxy(); initialize(baseServiceUrl); @@ -109,6 +114,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient { public FHIRToolingClient(String baseServiceUrl, String userAgent, String username, String password) throws URISyntaxException { preferredResourceFormat = ResourceFormat.RESOURCE_XML; + utils = getClientUtils(); utils.setUserAgent(userAgent); utils.setUsername(username); utils.setPassword(password); @@ -324,9 +330,12 @@ public class FHIRToolingClient extends FHIRBaseToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), + result = utils.issuePutRequest( + resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), - withVer(getPreferredResourceFormat(), "1.0"), headers, timeoutOperation); + withVer(getPreferredResourceFormat(), "1.0"), + headers, + timeoutOperation); result.addErrorStatus(410);// gone result.addErrorStatus(404);// unknown result.addErrorStatus(405); diff --git a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ResourceAddress.java b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ResourceAddress.java index 7ff64f2bc..e58b6fdaa 100644 --- a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ResourceAddress.java +++ b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ResourceAddress.java @@ -233,9 +233,8 @@ public class ResourceAddress { /** * For now, assume this type of location header structure. Generalize later: * http://hl7connect.healthintersections.com.au/svc/fhir/318/_history/1 - * - * @param serviceBase - * @param locationHeader + * + * @param locationResponseHeader */ public static ResourceAddress.ResourceVersionedIdentifier parseCreateLocation(String locationResponseHeader) { Pattern pattern = Pattern.compile(REGEX_ID_WITH_HISTORY); diff --git a/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/ClientUtilsTest.java b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/ClientUtilsTest.java index ac8c0ec7c..72ed5bebe 100644 --- a/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/ClientUtilsTest.java +++ b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/ClientUtilsTest.java @@ -100,11 +100,29 @@ public class ClientUtilsTest { } @Test - public void testResourceFormat() { - ResourceFormat format = ResourceFormat.RESOURCE_XML; - assertThat(format.getHeader()).isEqualTo("application/xml+fhir"); - format = ResourceFormat.RESOURCE_JSON; - assertThat(format.getHeader()).isEqualTo("application/json+fhir"); + public void testResourceFormatHeaders_GET() throws IOException, InterruptedException { + server.enqueue( + new MockResponse() + .setBody(new String(generateResourceBytes(patient))) + .addHeader("Content-Type", ResourceFormat.RESOURCE_JSON) + ); + ResourceRequest resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT); + RecordedRequest recordedRequest = server.takeRequest(); + assertThat(recordedRequest.getHeader("Accept")).isEqualTo("application/json+fhir"); + } + + @Test + public void testResourceFormatHeaders_POST() throws IOException, InterruptedException { + byte[] payload = generateResourceBytes(patient); + server.enqueue( + new MockResponse() + .setBody(new String(payload)) + .addHeader("Content-Type", "application/json+fhir") + .setResponseCode(201) + ); + ResourceRequest resourceRequest = clientUtils.issuePostRequest(serverUrl.uri(), payload, "application/json+fhir", TIMEOUT); + RecordedRequest recordedRequest = server.takeRequest(); + assertThat(recordedRequest.getHeader("Accept")).isEqualTo("application/json+fhir"); } @Test @@ -142,10 +160,8 @@ public class ClientUtilsTest { .addHeader("Content-Location", DUMMY_LOCATION) ); ResourceRequest resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT); - resourceRequest.addSuccessStatus(200); + assertThat(resourceRequest.getLocation()).isEqualTo(DUMMY_LOCATION); - assertTrue(resourceRequest.isSuccessfulRequest()); - assertTrue(patient.equalsDeep(resourceRequest.getPayload())); } @Test @@ -159,10 +175,7 @@ public class ClientUtilsTest { .addHeader("Content-Location", "Wrong wrong wrong") ); ResourceRequest resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT); - resourceRequest.addSuccessStatus(200); assertThat(resourceRequest.getLocation()).isEqualTo(DUMMY_LOCATION); - assertTrue(resourceRequest.isSuccessfulRequest()); - assertTrue(patient.equalsDeep(resourceRequest.getPayload())); } @Test @@ -174,17 +187,18 @@ public class ClientUtilsTest { .addHeader("Content-Type", "application/json+fhir") ); ResourceRequest resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT); - resourceRequest.addSuccessStatus(200); assertThat(resourceRequest.getLocation()).isNull(); - assertTrue(resourceRequest.isSuccessfulRequest()); - assertTrue(patient.equalsDeep(resourceRequest.getPayload())); } @Test public void testIssuePostRequest() throws IOException, InterruptedException { byte[] payload = generateResourceBytes(patient); server.enqueue( - new MockResponse().setBody(new String(payload)).addHeader("Content-Type", "application/json+fhir").addHeader("Location", DUMMY_LOCATION).setResponseCode(201) + new MockResponse() + .setBody(new String(payload)) + .addHeader("Content-Type", "application/json+fhir") + .addHeader("Location", DUMMY_LOCATION) + .setResponseCode(201) ); ResourceRequest resourceRequest = clientUtils.issuePostRequest(serverUrl.uri(), payload, "application/json+fhir", TIMEOUT); resourceRequest.addSuccessStatus(201); @@ -201,7 +215,11 @@ public class ClientUtilsTest { public void testIssuePutRequest() throws IOException, InterruptedException { byte[] payload = generateResourceBytes(patient); server.enqueue( - new MockResponse().setBody(new String(payload)).addHeader("Content-Type", "application/json+fhir").addHeader("Location", DUMMY_LOCATION).setResponseCode(200) + new MockResponse() + .setBody(new String(payload)) + .addHeader("Content-Type", "application/json+fhir") + .addHeader("Location", DUMMY_LOCATION) + .setResponseCode(200) ); ResourceRequest resourceRequest = clientUtils.issuePutRequest(serverUrl.uri(), payload, "application/json+fhir", TIMEOUT); resourceRequest.addSuccessStatus(200); diff --git a/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClientTest.java b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClientTest.java new file mode 100644 index 000000000..9386d2d6d --- /dev/null +++ b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClientTest.java @@ -0,0 +1,167 @@ +package org.hl7.fhir.dstu2.utils.client; + +import org.hl7.fhir.dstu2.model.*; +import org.hl7.fhir.utilities.http.HTTPHeader; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.*; + +import java.net.URI; +import java.net.URISyntaxException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.Mockito.*; + +public class FHIRToolingClientTest { + + private final Address address = new Address() + .setCity("Toronto") + .setState("Ontario") + .setCountry("Canada"); + private final HumanName humanName = new HumanName() + .addGiven("Mark") + .addFamily("Iantorno"); + private final Patient patient = new Patient() + .addName(humanName) + .addAddress(address) + .setGender(Enumerations.AdministrativeGender.MALE); + + private ClientUtils mockClientUtils; + private FHIRToolingClient toolingClient; + + @Captor + private ArgumentCaptor uriArgumentCaptor; + + @BeforeEach + public void beforeEach() throws URISyntaxException { + MockitoAnnotations.openMocks(this); + mockClientUtils = Mockito.mock(ClientUtils.class); + + toolingClient = new FHIRToolingClient("http://dummy-base-url.com", "dummy-user-agent") { + @Override + protected ClientUtils getClientUtils() { + return mockClientUtils; + } + }; + + /* + Need to reset here. When initialized, the client makes a call to getConformanceStatementQuick, which messes with + our expected calls. + */ + reset(mockClientUtils); + } + + @Test + public void testGetTerminologyCapabilities() throws URISyntaxException { + + Parameters expectedCapabilities = new Parameters(); + expectedCapabilities.addParameter().setName("name").setValue(new StringType("dummyValue")); + + when(mockClientUtils.issueGetResourceRequest(uriArgumentCaptor.capture(), Mockito.anyString(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(expectedCapabilities, 200, "location")); + Parameters actualCapabilities = toolingClient.getTerminologyCapabilities(); + + Mockito.verify(mockClientUtils).issueGetResourceRequest(ArgumentMatchers.any(URI.class), ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); + assertThat(actualCapabilities).isEqualTo(expectedCapabilities); + + assertThat(uriArgumentCaptor.getValue()).isEqualTo(new URI("http://dummy-base-url.com/metadata?mode=terminology")); + } + + @Test + public void testGetConformanceStatement() throws URISyntaxException { + + Conformance expectedConformance = new Conformance(); + expectedConformance.setCopyright("dummyCopyright"); + when(mockClientUtils.issueGetResourceRequest(uriArgumentCaptor.capture(), Mockito.anyString(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(expectedConformance, 200, "location")); + Conformance actualConformance = toolingClient.getConformanceStatement(); + + Mockito.verify(mockClientUtils).issueGetResourceRequest(ArgumentMatchers.any(URI.class), ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); + assertThat(actualConformance).isEqualTo(expectedConformance); + + assertThat(uriArgumentCaptor.getValue()).isEqualTo(new URI("http://dummy-base-url.com/metadata")); + } + + @Test + public void testGetConformanceStatementQuick() throws URISyntaxException { + + Conformance expectedConformance = new Conformance(); + expectedConformance.setCopyright("dummyCopyright"); + when(mockClientUtils.issueGetResourceRequest(uriArgumentCaptor.capture(), Mockito.anyString(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(expectedConformance, 200, "location")); + Conformance actualConformance = toolingClient.getConformanceStatementQuick(); + + Mockito.verify(mockClientUtils).issueGetResourceRequest(ArgumentMatchers.any(URI.class), ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); + assertThat(actualConformance).isEqualTo(expectedConformance); + + assertThat(uriArgumentCaptor.getValue()).isEqualTo(new URI("http://dummy-base-url.com/metadata?_summary=true")); + } + + @Test + void testRead() { + when(mockClientUtils.issueGetResourceRequest(uriArgumentCaptor.capture(), Mockito.anyString(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(patient, 200, "location")); + Patient actualPatient = toolingClient.read(Patient.class, "id"); + + Mockito.verify(mockClientUtils).issueGetResourceRequest(ArgumentMatchers.any(URI.class), ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); + assertThat(actualPatient).isEqualTo(patient); + + assertThat(uriArgumentCaptor.getValue().toString()).isEqualTo("http://dummy-base-url.com/Patient/id"); + } + + @Test + void testVRead() { + when(mockClientUtils.issueGetResourceRequest(uriArgumentCaptor.capture(), Mockito.anyString(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(patient, 200, "location")); + Patient actualPatient = toolingClient.vread(Patient.class, "id", "version"); + + Mockito.verify(mockClientUtils).issueGetResourceRequest(ArgumentMatchers.any(URI.class), ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); + assertThat(actualPatient).isEqualTo(patient); + + assertThat(uriArgumentCaptor.getValue().toString()).isEqualTo("http://dummy-base-url.com/Patient/id/_history/version"); + } + + @Test + void testCanonical() { + Bundle bundle = new Bundle(); + bundle.addEntry().setResource(patient); + when(mockClientUtils.issueGetResourceRequest(uriArgumentCaptor.capture(), Mockito.anyString(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(bundle, 200, "location")); + Patient actualPatient = toolingClient.getCanonical(Patient.class, "canonicalURL"); + + Mockito.verify(mockClientUtils).issueGetResourceRequest(ArgumentMatchers.any(URI.class), ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); + assertThat(actualPatient).isEqualTo(patient); + + assertThat(uriArgumentCaptor.getValue().toString()).isEqualTo("http://dummy-base-url.com/Patient?url=canonicalURL"); + } + + @Test + void testUpdate() { + final byte[] dummyBytes = "dummyBytes".getBytes(); + when(mockClientUtils.getResourceAsByteArray(any(Patient.class), anyBoolean(), anyBoolean())).thenReturn(dummyBytes); + when(mockClientUtils.issuePutRequest(uriArgumentCaptor.capture(), Mockito.any(byte[].class), Mockito.anyString(), Mockito.isNull(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(patient, 200, "location")); + Patient actualPatient = toolingClient.update(Patient.class, patient, "id"); + + Mockito.verify(mockClientUtils).issuePutRequest(ArgumentMatchers.any(URI.class), Mockito.any(byte[].class), ArgumentMatchers.anyString(), ArgumentMatchers.isNull(),ArgumentMatchers.anyInt()); + assertThat(actualPatient).isEqualTo(patient); + + assertThat(uriArgumentCaptor.getValue().toString()).isEqualTo("http://dummy-base-url.com/Patient/id"); + } + + @Test + void testValidate() { + final byte[] dummyBytes = "dummyBytes".getBytes(); + final OperationOutcome expectedOutcome = new OperationOutcome(); + OperationOutcome.OperationOutcomeIssueComponent issueComponent = expectedOutcome.addIssue(); + issueComponent.setSeverity(OperationOutcome.IssueSeverity.ERROR); + when(mockClientUtils.getResourceAsByteArray(any(Patient.class), anyBoolean(), anyBoolean())).thenReturn(dummyBytes); + when(mockClientUtils.issuePostRequest(uriArgumentCaptor.capture(), Mockito.any(byte[].class), Mockito.anyString(), Mockito.anyInt())) + .thenReturn(new ResourceRequest<>(expectedOutcome, 200, "location")); + + OperationOutcome actualOutcome = toolingClient.validate(Patient.class, patient, "id"); + assertThat(actualOutcome).isEqualTo(expectedOutcome); + + assertThat(uriArgumentCaptor.getValue().toString()).isEqualTo("http://dummy-base-url.com/Patient/$validate/id"); + } +} diff --git a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/utils/client/FhirToolingClientTest.java b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/utils/client/FhirToolingClientTest.java index 1fdc645fb..43de724c1 100644 --- a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/utils/client/FhirToolingClientTest.java +++ b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/utils/client/FhirToolingClientTest.java @@ -33,7 +33,6 @@ public class FhirToolingClientTest { @Captor private ArgumentCaptor> headersArgumentCaptor; - @BeforeEach void setUp() throws IOException, URISyntaxException { MockitoAnnotations.openMocks(this);