From c9f85111abef5355dd38d7f366484bbcfb5a7cd3 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Thu, 16 Jun 2016 07:42:06 -0400 Subject: [PATCH] Add some tests to GenericClient --- .../ca/uhn/fhir/context/ModelScanner.java | 3 + .../ca/uhn/fhir/rest/client/BaseClient.java | 16 +++ .../uhn/fhir/rest/client/GenericClient.java | 13 +- .../uhn/fhir/rest/client/IGenericClient.java | 5 + .../fhir/rest/client/GenericClientTest.java | 45 ++++++ .../ca/uhn/fhir/ctx/FhirContextDstu2Test.java | 7 + .../rest/client/GenericClientDstu2Test.java | 135 ++++++++++++++++-- .../fhir/context/FhirContextDstu3Test.java | 2 +- .../rest/client/GenericClientDstu3Test.java | 77 +++++++++- 9 files changed, 283 insertions(+), 20 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java index e3a8d64176c..e51a7d198bc 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java @@ -44,6 +44,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseBackboneElement; @@ -574,6 +575,8 @@ class ModelScanner { } } catch (IOException e) { throw new ConfigurationException("Failed to load model property file from classpath: " + "/ca/uhn/fhir/model/dstu/model.properties"); + } finally { + IOUtils.closeQuietly(str); } return retVal; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java index 2a7f1a44258..4386e9a7d35 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java @@ -70,6 +70,13 @@ import ca.uhn.fhir.util.OperationOutcomeUtil; public abstract class BaseClient implements IRestfulClient { + /** + * This property is used by unit tests - do not rely on it in production code + * as it may change at any time. If you want to capture responses in a reliable + * way in your own code, just use client interceptors + */ + static final String HAPI_CLIENT_KEEPRESPONSES = "hapi.client.keepresponses"; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseClient.class); private final IHttpClient myClient; @@ -89,6 +96,15 @@ public abstract class BaseClient implements IRestfulClient { myClient = theClient; myUrlBase = theUrlBase; myFactory = theFactory; + + /* + * This property is used by unit tests - do not rely on it in production code + * as it may change at any time. If you want to capture responses in a reliable + * way in your own code, just use client interceptors + */ + if ("true".equals(System.getProperty(HAPI_CLIENT_KEEPRESPONSES))) { + setKeepResponses(true); + } } protected Map> createExtraParams() { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java index d805de9da67..47f0567f663 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java @@ -76,6 +76,7 @@ import ca.uhn.fhir.rest.api.SummaryEnum; import ca.uhn.fhir.rest.client.api.IHttpClient; import ca.uhn.fhir.rest.client.api.IHttpRequest; import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException; +import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.gclient.IClientExecutable; import ca.uhn.fhir.rest.gclient.ICreate; import ca.uhn.fhir.rest.gclient.ICreateTyped; @@ -174,8 +175,8 @@ public class GenericClient extends BaseClient implements IGenericClient { @Override public IBaseConformance conformance() { - if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) { - throw new IllegalArgumentException("Must call fetchConformance() instead of conformance() for RI/DSTU3+ structures"); + if (myContext.getVersion().getVersion().isRi()) { + throw new IllegalArgumentException("Must call fetchConformance() instead of conformance() for RI/STU3+ structures"); } HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation(getFhirContext()); @@ -376,7 +377,7 @@ public class GenericClient extends BaseClient implements IGenericClient { } } - throw new RuntimeException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString())); + throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString())); } @@ -385,6 +386,12 @@ public class GenericClient extends BaseClient implements IGenericClient { // return doReadOrVRead(theType, theId, false, null, null); // } + /** + * @deprecated Use {@link LoggingInterceptor} as a client interceptor registered to your + * client instead, as this provides much more fine-grained control over what is logged. This + * method will be removed at some point (deprecated in HAPI 1.6 - 2016-06-16) + */ + @Deprecated public boolean isLogRequestAndResponse() { return myLogRequestAndResponse; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java index 4bd785e753b..ac49faf4b8d 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java @@ -37,6 +37,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.api.IRestfulClient; import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException; import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException; +import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.gclient.ICreate; import ca.uhn.fhir.rest.gclient.IDelete; import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped; @@ -288,7 +289,11 @@ public interface IGenericClient extends IRestfulClient { * * @param theLogRequestAndResponse * Should requests and responses be logged + * @deprecated Use {@link LoggingInterceptor} as a client interceptor registered to your + * client instead, as this provides much more fine-grained control over what is logged. This + * method will be removed at some point (deprecated in HAPI 1.6 - 2016-06-16) */ + @Deprecated void setLogRequestAndResponse(boolean theLogRequestAndResponse); /** diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java index 5626c7ea13d..966a608a569 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java @@ -15,7 +15,9 @@ import java.io.InputStream; import java.io.StringReader; import java.net.URLEncoder; import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.ReaderInputStream; @@ -33,6 +35,7 @@ import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicStatusLine; import org.hamcrest.Matchers; import org.hamcrest.core.StringContains; +import org.hl7.fhir.instance.model.api.IBaseResource; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -82,6 +85,8 @@ public class GenericClientTest { ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs()); + + System.setProperty(BaseClient.HAPI_CLIENT_KEEPRESPONSES, "true"); } private String extractBody(ArgumentCaptor capt, int count) throws IOException { @@ -89,6 +94,24 @@ public class GenericClientTest { return body; } + @Test + public void testInvalidCalls() { + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + try { + client.meta(); + fail(); + } catch (IllegalStateException e) { + assertEquals("Can not call $meta operations on a DSTU1 client", e.getMessage()); + } + try { + client.operation(); + fail(); + } catch (IllegalStateException e) { + assertEquals("Operations are only supported in FHIR DSTU2 and later. This client was created using a context configured for DSTU1", e.getMessage()); + } + } + private String getPatientFeedWithOneResult() { //@formatter:off String msg = "\n" + @@ -155,6 +178,9 @@ public class GenericClientTest { resp = client.create().resource(ourCtx.newXmlParser().encodeResourceToString(p1)).execute(); assertNull(resp.getCreated()); + ourLog.info("lastRequest: {}", ((GenericClient)client).getLastRequest()); + ourLog.info("lastResponse: {}", ((GenericClient)client).getLastResponse()); + ourLog.info("lastResponseBody: {}", ((GenericClient)client).getLastResponseBody()); } @Test @@ -1471,6 +1497,25 @@ public class GenericClientTest { } + @SuppressWarnings("deprecation") + @Test + public void testTransactionOldStyle() throws Exception { + String bundleStr = IOUtils.toString(getClass().getResourceAsStream("/bundle.json")); + Bundle bundle = ourCtx.newJsonParser().parseBundle(bundleStr); + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(bundleStr), Charset.forName("UTF-8"))); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + List input = new ArrayList(); + input.addAll(bundle.toListOfResources()); + client.transaction(input); + } + @Test public void testTransactionJson() throws Exception { String bundleStr = IOUtils.toString(getClass().getResourceAsStream("/bundle.json")); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/ctx/FhirContextDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/ctx/FhirContextDstu2Test.java index 41a2ce65721..a5032c6a712 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/ctx/FhirContextDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/ctx/FhirContextDstu2Test.java @@ -11,6 +11,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum; import ca.uhn.fhir.model.dstu2.valueset.MaritalStatusCodesEnum; +import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.util.TestUtil; public class FhirContextDstu2Test { @@ -23,6 +24,12 @@ public class FhirContextDstu2Test { TestUtil.clearAllStaticFieldsForUnitTest(); } + @Test(expected=DataFormatException.class) + public void testScanInvalid() { + FhirContext ctx = FhirContext.forDstu2(); + ctx.getResourceDefinition("InvalidResource"); + } + @Test public void testQueryBoundCode() { diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java index 4f96f461fd6..dafa628292b 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java @@ -19,6 +19,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.HashMap; import java.util.List; import org.apache.commons.io.IOUtils; @@ -48,15 +49,16 @@ import org.mockito.stubbing.Answer; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.ExtensionDt; +import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.dstu2.composite.IdentifierDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; import ca.uhn.fhir.model.dstu2.resource.Bundle.Link; +import ca.uhn.fhir.model.dstu2.resource.Conformance; import ca.uhn.fhir.model.dstu2.resource.Conformance.Rest; import ca.uhn.fhir.model.dstu2.resource.Conformance.RestSecurity; -import ca.uhn.fhir.model.dstu2.resource.Conformance; import ca.uhn.fhir.model.dstu2.resource.Encounter; import ca.uhn.fhir.model.dstu2.resource.Observation; import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; @@ -68,6 +70,7 @@ import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.UriDt; +import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.XmlParserDstu2Test; import ca.uhn.fhir.rest.api.MethodOutcome; @@ -77,6 +80,7 @@ import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory; import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.method.SearchStyleEnum; +import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.EncodingEnum; @@ -97,6 +101,23 @@ public class GenericClientDstu2Test { TestUtil.clearAllStaticFieldsForUnitTest(); } + @Test + public void testReadForUnknownType() throws Exception { + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + try { + client.read(new UriDt("1")); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("The given URI is not an absolute URL and is not usable for this operation: 1", e.getMessage()); + } + + try { + client.read(new UriDt("http://example.com/InvalidResource/1")); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Unable to determine the resource type from the given URI: ?aaaa", e.getMessage()); + } + } @Before public void before() { @@ -113,7 +134,6 @@ public class GenericClientDstu2Test { return body; } - private String getPatientFeedWithOneResult() { //@formatter:off String msg = "\n" + @@ -196,10 +216,10 @@ public class GenericClientDstu2Test { IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:8080/fhir"); Conformance conf = client.fetchConformance().ofType(Conformance.class).execute(); - + Rest rest = conf.getRest().get(0); RestSecurity security = rest.getSecurity(); - + List ext = security.getUndeclaredExtensionsByUrl("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris"); List tokenExts = ext.get(0).getUndeclaredExtensionsByUrl("token"); ExtensionDt tokenExt = tokenExts.get(0); @@ -208,8 +228,6 @@ public class GenericClientDstu2Test { } - - /** * See #322 */ @@ -229,10 +247,10 @@ public class GenericClientDstu2Test { IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:8080/fhir"); Conformance conf = client.fetchConformance().ofType(Conformance.class).execute(); - + Rest rest = conf.getRest().get(0); RestSecurity security = rest.getSecurity(); - + List ext = security.getUndeclaredExtensionsByUrl("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris"); List tokenExts = ext.get(0).getUndeclaredExtensionsByUrl("token"); ExtensionDt tokenExt = tokenExts.get(0); @@ -604,6 +622,73 @@ public class GenericClientDstu2Test { } + @Test + public void testDeleteByResource() throws Exception { + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "")); + when(myHttpResponse.getEntity().getContent()).then(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + int idx = 0; + + Patient pat = new Patient(); + pat.setId("Patient/123"); + + client.delete().resource(pat).execute(); + assertEquals("DELETE", capt.getAllValues().get(idx).getMethod()); + assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString()); + } + + @Test + public void testDeleteInvalidRequest() throws Exception { + Patient pat = new Patient(); + pat.setId("123"); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + try { + client.delete().resource(pat).execute(); + fail(); + } catch (IllegalArgumentException e){ + assertEquals("theResource.getId() must contain a resource type and logical ID at a minimum (e.g. Patient/1234), found: 123", e.getMessage()); + } + + try { + client.delete().resourceById(new IdDt("123")).execute(); + fail(); + } catch (IllegalArgumentException e){ + assertEquals("theId must contain a resource type and logical ID at a minimum (e.g. Patient/1234)found: 123", e.getMessage()); + } + + try { + client.delete().resourceById("", "123").execute(); + fail(); + } catch (IllegalArgumentException e){ + assertEquals("theResourceType can not be blank/null", e.getMessage()); + } + + try { + client.delete().resourceById("Patient", "").execute(); + fail(); + } catch (IllegalArgumentException e){ + assertEquals("theLogicalId can not be blank/null", e.getMessage()); + } + + try { + client.delete().resourceConditionalByType("InvalidType"); + fail(); + } catch (DataFormatException e){ + assertEquals("Unknown resource name \"InvalidType\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage()); + } + } + @Test public void testHistory() throws Exception { @@ -1504,10 +1589,10 @@ public class GenericClientDstu2Test { } @Test - public void testProviderWhereWeForgotToSetTheContext() throws Exception { + public void testProviderWhereWeForgotToSetTheContext() throws Exception { ApacheRestfulClientFactory clientFactory = new ApacheRestfulClientFactory(); // no ctx clientFactory.setServerValidationMode(ServerValidationModeEnum.NEVER); - + ourCtx.setRestfulClientFactory(clientFactory); try { @@ -1729,7 +1814,7 @@ public class GenericClientDstu2Test { ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString()); ourLog.info(capt.getValue().toString()); - + HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue(); String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8"); assertEquals("name=james", req); @@ -1772,7 +1857,7 @@ public class GenericClientDstu2Test { ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString()); ourLog.info(capt.getValue().toString()); - + HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue(); String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8"); assertEquals("name=james", req); @@ -1817,11 +1902,12 @@ public class GenericClientDstu2Test { @Override public InputStream answer(InvocationOnMock theInvocation) throws Throwable { return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")); - }}); + } + }); IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); int idx = 0; - + //@formatter:off client.search() .forResource("Encounter") @@ -2035,6 +2121,27 @@ public class GenericClientDstu2Test { } + @Test + public void testSearchWithMap() throws Exception { + String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + HashMap> params = new HashMap>(); + params.put("foo", Arrays.asList((IQueryParameterType)new DateParam("2001"))); + Bundle response = client.search(Patient.class, params); + + assertEquals("http://example.com/fhir/Patient?foo=2001", capt.getValue().getURI().toString()); + assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass()); + + } + @Test public void testSearchWithProfileAndSecurity() throws Exception { String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/FhirContextDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/FhirContextDstu3Test.java index 2f6f7c76434..f188b0bbf4d 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/FhirContextDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/FhirContextDstu3Test.java @@ -24,7 +24,7 @@ public class FhirContextDstu3Test { public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); } - + /** * See #344 */ diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java index 5ae701b0c78..af55c39d2eb 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java @@ -1,13 +1,13 @@ package ca.uhn.fhir.rest.client; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.matchesPattern; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -22,7 +22,6 @@ import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.ReaderInputStream; -import org.apache.commons.lang3.time.FastDateParser; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; @@ -56,6 +55,7 @@ import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum; import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.parser.CustomTypeDstu3Test; import ca.uhn.fhir.parser.CustomTypeDstu3Test.MyCustomPatient; import ca.uhn.fhir.parser.IParser; @@ -97,6 +97,18 @@ public class GenericClientDstu3Test { return body; } + @SuppressWarnings("deprecation") + @Test + public void testInvalidConformanceCall() { + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + try { + client.conformance(); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Must call fetchConformance() instead of conformance() for RI/STU3+ structures", e.getMessage()); + } + } + @Test public void testBinaryCreateWithFhirContentType() throws Exception { IParser p = ourCtx.newXmlParser(); @@ -588,6 +600,19 @@ public class GenericClientDstu3Test { assertEquals("http://example.com/fhir/Patient/222", capt.getAllValues().get(0).getURI().toASCIIString()); } + + @Test + public void testSearchForUnknownType() throws Exception { + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + try { + client.search(new UriDt("?aaaa")); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Unable to determine the resource type from the given URI: ?aaaa", e.getMessage()); + } + } + + @Test public void testUserAgentForBinary() throws Exception { IParser p = ourCtx.newXmlParser(); @@ -705,6 +730,54 @@ public class GenericClientDstu3Test { validateUserAgent(capt); } + @Test + public void testForceConformance() throws Exception { + final IParser p = ourCtx.newXmlParser(); + + final Conformance conf = new Conformance(); + conf.setCopyright("COPY"); + + final Patient patient = new Patient(); + patient.addName().addFamily("FAM"); + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + private int myCount = 0; + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + final String respString; + if (myCount == 1 || myCount == 2) { + ourLog.info("Encoding patient"); + respString = p.encodeResourceToString(patient); + } else { + ourLog.info("Encoding conformance"); + respString = p.encodeResourceToString(conf); + } + myCount++; + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE); + IGenericClient client = ourCtx.newRestfulGenericClient("http://testForceConformance.com/fhir"); + + client.read().resource("Patient").withId("1").execute(); + assertEquals(2, capt.getAllValues().size()); + assertEquals("http://testForceConformance.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString()); + assertEquals("http://testForceConformance.com/fhir/Patient/1", capt.getAllValues().get(1).getURI().toASCIIString()); + + client.read().resource("Patient").withId("1").execute(); + assertEquals(3, capt.getAllValues().size()); + assertEquals("http://testForceConformance.com/fhir/Patient/1", capt.getAllValues().get(2).getURI().toASCIIString()); + + client.forceConformanceCheck(); + assertEquals(4, capt.getAllValues().size()); + assertEquals("http://testForceConformance.com/fhir/metadata", capt.getAllValues().get(3).getURI().toASCIIString()); + } + private List> toTypeList(Class theClass) { ArrayList> retVal = new ArrayList>(); retVal.add(theClass);